I am testing a service which heavily relies on project reactor.
For many tests I am mocking the return value of the component responsible for API calls.
The tests are split over multiple files.
When I run the tests of one file, they are green, but when I execute all of the test files at once, some tests fail, with the error message indicating that the mocking did not succeed (Either the injected component returned null
, or the implementation of the actual component is invoked).
In the logs, there is no information about the mocking failing.
A code example:
interface API {
Flux<Bird> getBirds();
}
@Component
class BirdWatcher {
API api;
BirdWatcher(API api) {
this.api = api;
}
Flux<Bird> getUncommonBirds() {
return api.getBirds() // Although this is mocked in the test, in some runs it returns `null` or calls the implementation of the actual component
.filter(Bird::isUncommon);
}
}
@SpringBootTest
class BirdWatcherTests {
@Autowired
BirdWatcher birdWatcher;
@MockBean
API api;
@Test
void findsUncommonBirds() {
// Assemble
Bird birdCommon = new Bird("Sparrow", "common");
Bird birdUncommon = new Bird("Parrot", "uncommon");
Mockito.when(api.getBirds()).thenReturn(Flux.just(birdCommon, birdUncommon));
// Act
Flux<Bird> uncommonBirds = birdWatcher.getUncommonBirds();
// Assert
assertThat(uncommonBirds.collectList().block().size(), equalTo(1));
}
}
For me the issue seems like a race condition, but I don't know where and how this might happen, and how I can check and fix this.
I am using spring-boot-test:2.7.8
, pulling in org.mockito:mockito-core:4.5.1
org.mockito:mockito-junit-jupiter:4.5.1
, and org.junit.jupiter:junit-jupiter:5.8.2
, with gradle 7.8.
For reactor, spring-boot-starter-webflux:2.7.8
, depending on reactor:2.7.8
.
I don't really know what the problem was, but I fixed this by annotating each class with @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)