Search code examples
javaspringtestingjunitmockito

Mockito fails to verify that a method is never called


I have a Spring Boot application and the following JUnit 5 test where I want to ensure that applicationEventPublisher.publishEvent(any()) is never called. However, the test passed even if the method is actually called. And what's even weirder, if I switch from times(0) (or never()) to times(2), it fails because the method is called only once 😵‍💫

@ExtendWith(MockitoExtension.class)
public class EventHandlerTest {

  @Mock
  private ApplicationEventPublisher applicationEventPublisher;

  private EventHandler eventHandler;

  @BeforeEach
  void setUp() {
    releaseEventHandler = new ReleaseEventHandler(applicationEventPublisher);
  }

  @Test
  void doNothingWhenKafkaIsDisabled() {
    var event = new EventDTO();

    eventHandler.accept(releaseEvent);

    verify(applicationEventPublisher, never()).publishEvent(any());
  }

In my code, EventHandler reads events from a Kafka topic and produces a new event that is published to the Spring's event bus. What I'm checking is that the internal event is not produced under certain circumstances. The mock applicationEventPublisher is an interface from org.springframework.context.ApplicationEventPublisher.

Any idea?

UPDATE:

After some tests, it seems that the failure have something to do with ApplicationEventPublisher being a functional interface.

@FunctionalInterface
public interface ApplicationEventPublisher {

    default void publishEvent(ApplicationEvent event) {
        publishEvent((Object) event);
    }

    void publishEvent(Object event);

}

Solution

  • There are two methods in the interface:

    • void publishEvent(ApplicationEvent event)
    • void publishEvent(Object event)

    Make sure to verify the call that your application is actually calling (or not calling).

    You can either cast the return value (i.e. null) of any() to choose the correct overload, use a type witness, or use any(Class<?>):

    verify(applicationEventPublisher, never()).publishEvent((ApplicationEvent)any());
    verify(applicationEventPublisher, never()).publishEvent(any<ApplicationEvent>());
    verify(applicationEventPublisher, never()).publishEvent(any(ApplicationEvent.class));
    

    Do note that any(Class<?>) does not match null. Use nullable(Class<?>) if you want to match null too in this case.