Version of Spring Boot: 1.4.0.M3
I have an integration test, annotated with
@RunWith(SpringRunner::class)
@SpringBootTest
@AutoConfigureMockMvc
and where I have
@MockBean
private lateinit var mockApplicationEventPublisher: ApplicationEventPublisher
@Autowired
private lateinit var mockMvc: MockMvc
Kotlin code, equivalent to
@MockBean
private ApplicationEventPublisher mockApplicationEventPublisher;
@Autowired
private MockMvc mockMvc;
The controller under test does call publishEvent()
on the event publisher, but when I verify that the calls have been made using
verify(mockApplicationEventPublisher).publishEvent(ScoreSubmittedEvent()))
I get the following error:
Wanted but not invoked:
org.springframework.context.ApplicationEventPublisher#0 bean.publishEvent(...);
-> at com.ninja_squad.ng2propack.pack.ScoreControllerTest.should submit score(ScoreControllerTest.kt:89)
Actually, there were zero interactions with this mock.
When I debug, I notice that the publisher in the test is indeed a Mockito-generated proxy, but that the publisher injected in the controller under test is the non-mocked instance of org.springframework.web.context.support.GenericWebApplicationContext
.
I guess the root caus is that the bean implementing ApplicationEventPublisher is not an actual separate bean, but is the spring application context itself.
A workaround would be to use my own event publisher bean that would simply delegate to the actual spring event publisher, but that's something I shouldn't have to do.
Comment From: philwebb
As far as I can tell this is a limitation of the Spring Framework. It appears that an ApplicationEventPublisher
cannot be registered as a regular bean. Take a look at AbstractApplicationContext.prepareBeanFactory
and specifically the Javadoc for beanFactory.registerResolvableDependency
.
You could add a additional bean to your test application context and use @EventListener
to verify the event was sent. Alternatively you might be able to spy on the ApplicationEventMulticaster
.
Comment From: jnizet
OK. I'll open a bug for Spring Framework then, because I think that workarounds shouldn't be necessary to support that common use-case.
Comment From: kgemmert-r7
Is there any update on that bug report, I am hitting a similar problem.
Comment From: snicoll
@kgemmert-r7 this issue is closed, check the issue that @jnizet has created.
Comment From: renannprado
I've just had the same issue. My workaround was the following
@Bean
@Primary
GenericApplicationContext genericApplicationContext(final GenericApplicationContext gac) {
return Mockito.spy(gac);
}
Comment From: idrisssakhi
Version of Spring Boot: 1.4.0.M3
I have an integration test, annotated with
@RunWith(SpringRunner::class) @SpringBootTest @AutoConfigureMockMvc
and where I have
``` @MockBean private lateinit var mockApplicationEventPublisher: ApplicationEventPublisher
@Autowired private lateinit var mockMvc: MockMvc
```
Kotlin code, equivalent to
``` @MockBean private ApplicationEventPublisher mockApplicationEventPublisher;
@Autowired private MockMvc mockMvc;
```
The controller under test does call
publishEvent()
on the event publisher, but when I verify that the calls have been made using
verify(mockApplicationEventPublisher).publishEvent(ScoreSubmittedEvent()))
I get the following error:
Wanted but not invoked: org.springframework.context.ApplicationEventPublisher#0 bean.publishEvent(...); -> at com.ninja_squad.ng2propack.pack.ScoreControllerTest.should submit score(ScoreControllerTest.kt:89) Actually, there were zero interactions with this mock.
When I debug, I notice that the publisher in the test is indeed a Mockito-generated proxy, but that the publisher injected in the controller under test is the non-mocked instance of
org.springframework.web.context.support.GenericWebApplicationContext
.I guess the root caus is that the bean implementing ApplicationEventPublisher is not an actual separate bean, but is the spring application context itself.
A workaround would be to use my own event publisher bean that would simply delegate to the actual spring event publisher, but that's something I shouldn't have to do.
@TestConfiguration static class contextConfiguration {
@Bean
@Primary
public ApplicationEventPublisher applicationEventPublisher(ApplicationEventPublisher app) {
return Mockito.spy(app);
}
}