Jean-Baptiste Nizet opened SPR-14335 and commented

This is a followup to this bug posted on the Spring Boot project:

  • https://github.com/spring-projects/spring-boot/issues/6060

ApplicationEventPublisher, which is a direct dependency of application components that must publish events, can't be mocked as other beans in Spring Boot tests, because it's not a "regular" Spring bean. Just testing that an event has been fired by a method thus requires workarounds such as defining a fake listener bean, and I think that workaround shouldn't be necessary.


Affects: 4.3 RC2

5 votes, 6 watchers

Comment From: spring-projects-issues

Juergen Hoeller commented

This is unfortunately not trivial since such "resolvable dependencies" are implicitly kind-of primary, that is, being picked in case of non-unique matches. We'll have to find some explicit way of expressing that a mock intends to override a resolvable dependency.

Comment From: spring-projects-issues

Stéphane Nicoll commented

Maybe we can have a special case at the Spring Boot level? something around @MockBean?

Comment From: nekperu15739

Hi, im facing the same problem, and for now i solve the problem using TestConfiguration:

@SpringBootTest
class MyUseCaseIT {

  @Autowired private ApplicationEventPublisher publisher;
  @Autowired private MyService service;

@Test
  void callUseCase() {
var event = mock(MyEvent.class);
    doNothing().when(publisher).publishEvent(event);

service.useCase();

    verify(publisher).publishEvent(event);
}


@TestConfiguration
  static class MockitoPublisherConfiguration {

    @Bean
    @Primary
    ApplicationEventPublisher publisher() {
      return mock(ApplicationEventPublisher.class);
    }
  }

Comment From: victordfb

I'm having the same issue here. It would be nice to have such feature.

Comment From: LaSylv

Maybe dig around @RecordApplicationEvents/ org.springframework.test.context.event.ApplicationEvents ?

Comment From: Cpt76

Ciao, sto affrontando lo stesso problema e per ora risolvo il problema utilizzando TestConfiguration:

``` @SpringBootTest class MyUseCaseIT {

@Autowired private ApplicationEventPublisher publisher; @Autowired private MyService service;

@Test void callUseCase() { var event = mock(MyEvent.class); doNothing().when(publisher).publishEvent(event);

service.useCase();

verify(publisher).publishEvent(event);

}

@TestConfiguration static class MockitoPublisherConfiguration {

@Bean
@Primary
ApplicationEventPublisher publisher() {
  return mock(ApplicationEventPublisher.class);
}

} ```

This workaround doesn't work when using webflux, I don't know why... single tests work in isolation, but when multiple tests are runned together flatMap is not working, it seems another thread is used.

Comment From: sbrannen

Closing in favor of the @RecordApplicationEvents feature introduced in spring-test in Spring Framework 5.3.3. See the reference documentation for details.

If you find that @RecordApplicationEvents does not meet your needs, please create a new ticket.

Comment From: imwower

Hi, im facing the same problem, and for now i solve the problem using TestConfiguration:

``` @SpringBootTest class MyUseCaseIT {

@Autowired private ApplicationEventPublisher publisher; @Autowired private MyService service;

@Test void callUseCase() { var event = mock(MyEvent.class); doNothing().when(publisher).publishEvent(event);

service.useCase();

verify(publisher).publishEvent(event);

}

@TestConfiguration static class MockitoPublisherConfiguration {

@Bean
@Primary
ApplicationEventPublisher publisher() {
  return mock(ApplicationEventPublisher.class);
}

} ```

also remember to import this configuration on your test class:

@Import(MockitoPublisherConfiguration.class)
@SpringBootTest
class MyUseCaseIT {
 ...