@MockBean results in NullPointerException for @SpringBatchTest in Junit 5

Viewed 380

I am trying to use the @MockBean annotation in my Spring Batch Test, but I am unable to get it to work. I have simplified my test to it's most basic form for this post. Essentially, @Autowired works (so I know the class is being picked up by Spring), but when I replace it with the @MockBean annotation, the bean is not mocked (it's null). Any idea what I could be doing wrong?

This works fine.

@SpringBatchTest
@WebAppConfiguration
@ContextConfiguration(classes = {TestAppConfig.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@TestPropertySource("classpath:application.properties")
public class EmailQueueBatchConfigTestFail {

    @Autowired
    private AppUserEmailSender appUserEmailSender;

    @Test
    public void test() {
        if (appUserEmailSender == null) {
            System.out.println("null");
        }
    }
}

However, the mocked object here is null

@SpringBatchTest
@WebAppConfiguration
@ContextConfiguration(classes = {TestAppConfig.class})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@TestPropertySource("classpath:application.properties")
public class EmailQueueBatchConfigTestFail {

    @MockBean
    private AppUserEmailSender appUserEmailSender;

    @Test
    public void test() {
        if (appUserEmailSender == null) {
            System.out.println("null");
        }
    }
}
1 Answers

It turns out that if you use the annotations @MockBean and @TestExecutionListeners in the same test class, the MockitoTestExecutionListener may not be called. To remedy this, you need to add TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS to the @TestExecutionListeners annotation.

So a corrected version would look like...

@SpringBatchTest
@WebAppConfiguration
@ContextConfiguration(classes = {TestAppConfig.class})
@TestExecutionListeners(
        listeners = {DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class},
        mergeMode = TestExecutionListeners.MergeMode.MERGE_WITH_DEFAULTS)
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
@TestPropertySource("classpath:application.properties")
@TestPropertySource(properties = "app.scheduling.enable=false") // disable @Scheduled annotation
public class SimpleTest {

    @MockBean
    private AppUserEmailSender appUserEmailSender;

    @Test
    public void test() throws Exception {
        when(appUserEmailSender.send(any())).thenReturn(new EmailQueue());
    }
}
Related