You are mixing things up here. There is an important difference between @Mock
and @MockBean
.
You use the first annotation if you want to write a unit test without any Spring Context support (speak @SpringBootTest
, @DataJpaTest
, etc.). For such tests, you can use @Mock
and @InjectMocks
.
As you are writing an integration test (you are starting the whole context with @SpringBootTest
), you work with managed Spring beans inside your test. Hence you are not writing a unit test anymore.
If you want to replace a Spring bean with a mocked version of it inside your Spring Test Context, you have to use @MockBean
:
@SpringBootTest(classes = TestApp.class)
@RunWith(SpringRunner.class)
@RunWith(MockitoJUnitRunner.class) // will do the Captor initialization for you
public class TestClass {
@Captor
private ArgumentCaptor<Object> captor;
@MockBean
private FetchFileDetailsDAO dao;
@Autowired
private FileEventListener listener;
@Test
@Transactional
@Rollback(true)
public void test() throws Exception {
FileEvent ev = new FileEvent();
// ...
listener.onApplicationEvent(ev);
verify(dao, times(1)).getDetailsForFile((String)captor.capture())
}
Starting the whole context however for this test is IMHO overkill. You are better off writing a good old unit test with just JUnit and Mockito.
In addition to this, also I would rethink what benefit your current tests adds to your project as it is literally duplicating the business logic. Maybe there is more code that is not present here.
You can find a more detailed summary for the difference between @Mock and @MockBean in this article.
CLICK HERE to find out more related problems solutions.