Description
Hello Spring Boot team!
Today a colleague of mine came across strange behaviour when writing some JUnit 5 tests. It seems that @MochBean
annotated fields, or more specifically the actual mocks behind that, are not reset for @Test
methods residing in @Nested
inner classes.
Example:
@SpringBootTest
@ExtendWith(SpringExtension.class)
class FailingTests {
@MockBean
ServiceB serviceB;
@Autowired
ServiceA cut;
@Nested
class NestedTest {
@Test
void mockWasInvokedOnce() {
cut.foo();
verify(serviceB, times(1)).bar();
}
@Test
void mockWasInvokedTwice() {
cut.foo();
cut.foo();
verify(serviceB, times(2)).bar();
}
}
}
One of these tests will fail because the mock will have been invoked 3 times at that point.
Tested with Spring Boot 2.0.1.BUILD-SNAPSHOT
and JUnit 5.1.0
on 2018-03-13
at around 8:00 PM
. (also tested with 2.0.0.RELEASE
earlier)
I created a simple example application (thx start.spring.io ;) ) to reproduce the issue: https://github.com/slu-it/bug-spring-mockbean-reset
I also tried to find the cause of the issue, but I might have underestimated the complexity of the spring-test
and spring-boot-test
libraries... As far as I can see, the application context returned from the TestContext
instance for tests within the @Nested
class does not include references to the ServiceB
bean. (From debugging MockitoTestExecutionListener
)
When I debug the same location for a test without the @Nested
part, the returned context contains a clearly identifiable instance of ServiceB
.
I think the correct behaviour would be to have a parent child relationships between application contexts in case of inner classes (like @Nested
JUnit 5 test classes).