I'm facing some problems when trying to inject a bean with the annotation @MockBean inside a Junit test. As a result I get the real service injected instead of the mocked one, but the weird behavior is that this only happens when running tests with maven verify (together with other integration tests).
Basically, the bean I want to mock is injected inside a Listener (@Component) that is triggered by a message sent on the queue during the integration test. When the listener runs, the service inside it is the real one instead of the mocked one.
It seems to me that, when running other tests, the real bean is previously injected inside the context and @MockBean, although it should restart the spring context, does not replace the existing bean with the mocked one when it encounters a bean of the same type.
This is really a strange behavior, because documentation says "Any existing single bean of the same type defined in the context will be replaced by the mock". Well, this is not happening.
Below you find snippets showing how this is done.
Service to be mocked is:
@Slf4j
@Service
@Transactional
public class SomeServiceImpl implements SomeService {
@Override
@Async
public void doStuff(){
...
}
}
A listener that injects my service like this
@Slf4j
@Component
@Transactional
public class SagaListener {
@Autowired
private SomeService someService;
@JmsListener(destination = "${mydestinationtopic}", containerFactory = "myFactory",
subscription = "my-subscription", selector = "eventType =
'MY_EVENT'" )
public void receive(MyEventClass event) {
someService.doStuff();
}
}
And here is my test class
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class SagaListenerIT {
@MockBean
private SomeService someService;
@Autowired
private Sender sender;
@Test
public void createNamespaceSuccess() throws InterruptedException {
...
sender.send(event, event.getEventType(), myTopic);
BDDMockito.then(someService).should().doStuff();
}
}
As a result I get that mockito says that someService made 0 invokations, and this is because the real service is being called.
Why isn't @MockBean replacing the real bean? Should't the context be reinitialized?
I've tried to add @DirtiesContext annotation in other tests and in that case everything works, but this is not a clean solution.
here is a portion of my pom where failsafe plugin is defined. It's a really simple one by the way:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
Thank you
DirtiesContext
(, I see,) is to restore mocked beans(="clean dirty context")...so the contrary of your issue (and not on the annotated test, but preceding or (by default) the following ones) - please clarify this. And else: the significant differences between maven and IDE testing are in "class loading" and probably "test execution order".. – Brownlee