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);
}
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.