Tengo un problema con una prueba de integración de primavera.
El comportamiento:
Cuando ejecuto la siguiente prueba de forma aislada, tiene éxito.
Sin embargo, cuando se ejecutan todas las pruebas, muchas de ellas, incluida la siguiente, tienen un error.
Cuando ignoro la prueba a continuación y ejecuto todas las pruebas, todas tienen éxito.
No he incluido el error stacktrace porque está muy relacionado con nuestra lógica comercial y sospecho que el error está relacionado con mi uso de la prueba de arranque de primavera @SpyBean .
Aquí está la prueba:
@RunWith(SpringRunner.class) @ActiveProfiles(profiles = "test") @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) ... @Autowired private TestRestTemplate restTemplate; @Autowired private DataKeyStore dataKeyStore; @SpyBean private TokenTools tokenTools; ... @Test public void myTest() throws Exception { doReturn("someGeneratedToken") .doReturn("someGeneratedToken") .doCallRealMethod() .when(tokenTools) .createToken(any(TokenProfile.class), anyString(), anyString()); ... Tenga en cuenta que DataKeyStore es una dependencia de TokenTools .
Como dije anteriormente, sospecho que las pruebas se están pisando entre sí y mi @SpyBean de alguna manera se filtra en otras clases de prueba...
Mi pregunta es ¿cómo puedo asegurarme de que esta prueba no pise las otras pruebas? Probé la anotación @DirtiesContext en vano...
Además, lo que me desconcierta es que @SpyBean ya está reiniciado (según la documentación/javadoc).
Alguien puede ayudarme porfavor?
editar : usar mi IDE para depurar las pruebas indica que TokenTools se instancia solo dos veces para todas las pruebas: una vez en la inicialización de las pruebas y una segunda vez para crear el @SpyBean para la prueba anterior. El resto de las pruebas que se ejecutan después de la prueba anterior utilizan la segunda instancia, es decir, la instancia de @SpyBean ...
Recientemente me encontré con el mismo problema. Asegúrese de configurar el modo de clase correcto para su anotación @DirtiesContext .
De forma predeterminada, @DirtiesContext restablecerá @SpyBean después de la clase de prueba completa. Probablemente desee restablecerlo antes o después de cada método de prueba.
Así que agregue @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) o @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD) a su clase de prueba.
Puedo confirmar que @DirtiesContext tampoco funcionó para nosotros. Tuvimos problemas para inicializar la base de datos (usando Liquibase) para el nuevo contexto después de que se cerró el contexto anterior (mediante la anotación @DirtiesContext ).
Terminamos nombrando el contexto de prueba de Spring de manera diferente para las pruebas que están fingiendo algunos beneficios:
P.ej:
@RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration(classes = SpringBootApp.class, name = "mainContext") public class TestThatDoesntFakeBeans(){ } @RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration(classes = SpringBootApp.class, name = "contextWithFakeBean") public class TestThatFakeBeans(){ @SpyBean //... }De esta manera, se crea un contexto Spring separado para cada nombre. Los contextos con el mismo nombre son reutilizados por las pruebas. Pero, por supuesto, debe asegurarse de que las pruebas con el mismo nombre de contexto no se afecten entre sí.
@SpyBean parece no reiniciarse después de cada prueba, lo que genera un comportamiento inusual. Sugeriría usar Mockito @Spy en su lugar y verificar si el problema persiste.
import org.mockito.Spy .... @RunWith(SpringRunner.class) @ActiveProfiles(profiles = "test") @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) ... @Autowired private TestRestTemplate restTemplate; @Autowired private DataKeyStore dataKeyStore; @Spy private TokenTools tokenTools; ... @Test public void myTest() throws Exception { doReturn("someGeneratedToken") .doReturn("someGeneratedToken") .doCallRealMethod() .when(tokenTools) .createToken(any(TokenProfile.class), anyString(), anyString()); ...