www taglibs springframework sec resolved org form cannot spring unit-testing spring-test

springframework - spring-security-taglibs



RedefiniciĆ³n de los granos de primavera en el entorno de prueba de la unidad (13)

¿Tal vez podrías usar calificadores para tus frijoles? Debería redefinir los beans que desea simular en un contexto de aplicación separado y etiquetarlos con una "prueba" de calificador. En sus pruebas unitarias, al cablear sus granos, siempre especifique la "prueba" del calificador para usar las maquetas.

estamos utilizando Spring para mis aplicaciones, y el marco Spring Testing para pruebas unitarias. Sin embargo, tenemos un pequeño problema: el código de la aplicación carga un contexto de aplicación Spring desde una lista de ubicaciones (archivos xml) en el classpath. Pero cuando ejecutamos nuestras pruebas unitarias, queremos que algunos de los beans de Spring sean simulacros en lugar de clases completas de implementación. Además, para algunas pruebas unitarias queremos que algunos frijoles se conviertan en simulacros, mientras que para otras pruebas unitarias queremos que otros frijoles se conviertan en simulacros, ya que estamos probando diferentes capas de la aplicación.

Todo esto significa que quiero redefinir beans específicos del contexto de la aplicación y actualizar el contexto cuando lo desee. Al hacer esto, quiero redefinir solo una pequeña porción de los beans ubicados en uno (o varios) archivos de definición de beans xml originales. No puedo encontrar una manera fácil de hacerlo. Siempre se considera que Spring es un marco amigable para las pruebas unitarias, así que me falta algo aquí.

¿Tienes alguna idea de cómo hacerlo?

Gracias.


Aquí hay algunas soluciones muy complicadas y potentes.

Pero hay una forma LEJOS, mucho más sencilla de lograr lo que Stas ha pedido, que no implica modificar nada más que una línea de código en el método de prueba. Funciona para pruebas unitarias y pruebas de integración de Spring por igual, para dependencias autocableadas, campos privados y protegidos.

Aquí está:

junitx.util.PrivateAccessor.setField(testSubject, "fieldName", mockObject);



Fácil. Utiliza un contexto de aplicación personalizado para las pruebas de su unidad. O no usa uno y crea e inyecta manualmente sus granos.

Me parece que las pruebas pueden ser demasiado amplias. La prueba unitaria trata de probar, bueno, unidades. Un Spring Bean es un buen ejemplo de una unidad. No debería necesitar un contexto de aplicación completo para eso. Me parece que si su unidad de prueba es de tan alto nivel que necesita cientos de frijoles, conexiones de bases de datos, etc., entonces tiene una prueba de unidad realmente frágil que se romperá en el próximo cambio, será difícil de mantener y realmente no es así. t agregar mucho valor.


Mira este tutorial con la anotación @InjectedMock

Me ahorró mucho tiempo. Usted solo usa

@Mock SomeClass mockedSomeClass @InjectMock ClassUsingSomeClass service @Before public void setUp() { MockitoAnnotations.initMocks(this); }

y todos tus problemas están resueltos Mockito reemplazará la inyección de dependencia de primavera con un simulacro. Simplemente lo usé yo mismo y funciona genial.


No necesita usar ningún contexto de prueba (no importa si está basado en XML o Java). Desde Spring boot 1.4, está disponible la nueva anotación @MockBean que introdujo el soporte nativo para burlarse y espiar de Spring Beans.


No tengo los puntos de reputación para apilar la respuesta de Duffymo, pero solo quería hacer sonar y decir que era la respuesta "correcta" para mí.

Cree una instancia de FileSystemXmlApplicationContext en la configuración de la prueba de su unidad con un applicationContext.xml personalizado. En ese xml personalizado, en la parte superior, haz lo que indique un duffymo. A continuación, declare sus beans simulados, fuentes de datos que no sean JNDI, etc., que anularán los ID declarados en la importación.

Trabajó como un sueño para mí.


Puede utilizar la función de import en el contexto de su aplicación de prueba para cargar los beans prod y anular los que desee. Por ejemplo, mi fuente de datos de prod generalmente se adquiere a través de la búsqueda de JNDI, pero cuando pruebo uso una fuente de datos de DriverManager para no tener que iniciar el servidor de aplicaciones para probar.


Quiero hacer lo mismo y lo encontramos esencial.

El mecanismo actual que usamos es bastante manual pero funciona.

Digamos, por ejemplo, que desea burlarse del frijol de tipo Y. Lo que hacemos es que cada frijol que tiene esa dependencia implementamos una interfaz: "IHasY". Esta interfaz es

interface IHasY { public void setY(Y y); }

Luego en nuestra prueba llamamos al método util ...

public static void insertMock(Y y) { Map invokers = BeanFactory.getInstance().getFactory("core").getBeansOfType(IHasY.class); for (Iterator iterator = invokers.values().iterator(); iterator.hasNext();) { IHasY invoker = (IHasY) iterator.next(); invoker.setY(y); } }

No quiero crear un archivo xml completo solo para inyectar esta nueva dependencia y es por eso que me gusta esto.

Si está dispuesto a crear un archivo de configuración xml, entonces el camino a seguir sería crear una nueva fábrica con los beans modelo y convertir a su fábrica predeterminada en la fábrica principal. Asegúrese de cargar todos los granos de la fábrica infantil nueva. Al hacer esto, la sub-fábrica anulará los granos en la fábrica principal cuando los id del grano sean los mismos.

Ahora si, en mi prueba, si pudiera crear una fábrica mediante programación, sería increíble. Tener que usar xml es demasiado engorroso. Estoy buscando crear esa fábrica infantil con código. Entonces cada prueba puede configurar su fábrica de la manera que quiera. No hay razón para que una fábrica como esa no funcione.


También puede escribir sus pruebas de unidad para no requerir ninguna búsqueda en absoluto:

@ContextConfiguration(locations = { "classpath:/path/to/test-config.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class MyBeanTest { @Autowired private MyBean myBean; // the component under test @Test public void testMyBean() { ... } }

Esto proporciona una manera fácil de mezclar y combinar archivos de configuración reales con archivos de configuración de prueba.

Por ejemplo, al usar Hibernate, podría tener mi bean sessionFactory en un archivo de configuración (para ser utilizado tanto en las pruebas como en la aplicación principal), y tener por dataSource Bean en otro archivo de configuración (uno podría usar DriverManagerDataSource a un archivo de configuración). db de memoria, el otro podría usar una búsqueda JNDI).

Pero, definitivamente, @cletus''s atención a @cletus''s advertencia de @cletus''s ;-)


Una de las razones por las cuales spring se describe como "prueba amigable" es porque puede ser fácil simplemente nuevo o burlarse de algo en la prueba unitaria.

Alternativamente, hemos utilizado la siguiente configuración con gran éxito, y creo que está bastante cerca de lo que desea, lo recomiendo encarecidamente :

Para todos los beans que necesitan implementaciones diferentes en contextos diferentes, cambie al cableado basado en anotaciones. Puedes dejar a los demás como están.

Implementar el siguiente conjunto de anotaciones

<context:component-scan base-package="com.foobar"> <context:include-filter type="annotation" expression="com.foobar.annotations.StubRepository"/> <context:include-filter type="annotation" expression="com.foobar.annotations.TestScopedComponent"/> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> </context:component-scan>

A continuación, anote sus implementaciones en vivo con @Repository, sus implementaciones de stub con @StubRepository, cualquier código que debería estar presente en el dispositivo de prueba de la unidad SOLAMENTE con @TestScopedComponent. Es posible que necesites un par de anotaciones más, pero este es un gran comienzo.

Si tiene mucho spring.xml, probablemente necesite crear algunos nuevos archivos xml de primavera que, básicamente, solo contienen las definiciones de exploración de componentes. Normalmente solo anexaría estos archivos a su lista regular @ContextConfiguration. La razón de esto es porque con frecuencia terminas con diferentes configuraciones de escaneos contextuales (confía en mí, harás al menos 1 anotación más si estás haciendo pruebas web, lo que hace que haya 4 combinaciones relevantes)

Entonces básicamente usas el

@ContextConfiguration(locations = { "classpath:/path/to/root-config.xml" }) @RunWith(SpringJUnit4ClassRunner.class)

Tenga en cuenta que esta configuración no le permite tener combinaciones alternas de datos auxiliares / en vivo. Probamos esto, y creo que eso causó un desastre. No recomendaría a nadie;) O bien enviamos el listón completo o todos los servicios en vivo.

Principalmente usamos dependencias de stub auto-cableadas cuando probamos GUI cerca de cosas donde las dependencias son usualmente bastante sustanciales. En áreas más limpias del código, utilizamos pruebas unitarias más regulares.

En nuestro sistema tenemos los siguientes archivos xml para componente-scan:

  • para la producción web regular
  • para iniciar la web solo con stubs
  • para pruebas de integración (en junit)
  • para pruebas unitarias (en junit)
  • para pruebas de web de selenio (en junio)

Esto significa que tenemos totalmente 5 configuraciones diferentes para todo el sistema con las que podemos iniciar la aplicación. Como solo utilizamos anotaciones, la primavera es lo suficientemente rápida como para autoconectar incluso las pruebas unitarias que queremos con cable. Sé que esto no es tradicional, pero es realmente genial.

Las pruebas de integración se ejecutan con la configuración completa en vivo, y una o dos veces he decidido ser realmente pragmático y quiero tener 5 cableados en vivo y un solo simulacro:

public class HybridTest { @Autowired MyTestSubject myTestSubject; @Test public void testWith5LiveServicesAndOneMock(){ MyServiceLive service = myTestSubject.getMyService(); try { MyService mock = EasyMock.create(...) myTestSubject.setMyService( mock); .. do funky test with lots of live but one mock object } finally { myTestSubject.setMyService( service); } } }

Sé que los puristas de la prueba me van a dar todo esto. Pero a veces es solo una solución muy pragmática que resulta ser muy elegante cuando la alternativa sería realmente fea. De nuevo, usualmente está en esas áreas cercanas a la guía.


propondría una TestClass personalizada y algunas reglas sencillas para las ubicaciones de spring bean.xml

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath*:spring/*.xml", "classpath*:spring/persistence/*.xml", "classpath*:spring/mock/*.xml"}) @Transactional @TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class, DirtiesContextTestExecutionListener.class}) public abstract class AbstractHibernateTests implements ApplicationContextAware { /** * Logger for Subclasses. */ protected final Logger LOG = LoggerFactory.getLogger(getClass()); /** * The {@link ApplicationContext} that was injected into this test instance * via {@link #setApplicationContext(ApplicationContext)}. */ protected ApplicationContext applicationContext; /** * Set the {@link ApplicationContext} to be used by this test instance, * provided via {@link ApplicationContextAware} semantics. */ @Override public final void setApplicationContext( final ApplicationContext applicationContext) { this.applicationContext = applicationContext; } }

si hay mock-bean.xml en la ubicación especificada, anularán todos los bean.xml "reales" en las ubicaciones "normales"; sus ubicaciones normales pueden diferir

pero ... nunca mezclaría frijoles simulados y no falsos, es difícil rastrear problemas cuando la aplicación envejece.