I wanted to do integration testing of my API.
@RestController
@RequestMapping("/api/v1")
public class TestController {
@Autowired
TestService testService;
@RequestMapping("/welcome")
public String welcomeMessage(@RequestParam("name") String name) {
return testService.welcomeMessage(name);
}
}
Below are the service interface and its implementation:
public interface TestService {
public String welcomeMessage(String name);
}
public class TestServiceImpl implements TestService{
@Autowired
TestRepository repo;
@Override
public String welcomeMessage(String name) {
repo.save(new StringEntity(name));
return "Hello "+name;
}
}
Below is the Test Case:
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class MockitoTestingApplicationTests {
@Autowired
MockMvc mvc;
@MockBean
TestService testService;
@MockBean
TestController testController;
@Test
public void contextLoads() throws Exception {
Mockito.when(testController.welcomeMessage(ArgumentMatchers.anyString())).thenCallRealMethod();
Mockito.when(testService.welcomeMessage(ArgumentMatchers.anyString())).thenCallRealMethod();
mvc.perform(get("/api/v1/welcome").param("name", "dude")).andExpect(status().isOk());
}
}
I have a few questions.
when I'm executing the above code it is throwing an error saying cannot call real method on abstract methods. And When I'm mocking the TestServiceImpl
, It is throwing NullPointerException
in the Controller because the TestService
is null. How should I fix that?
How should I mock the repository layer when we are using MongoDB. when I try to Mock MongoTemplate
, It is throwing an error saying MongoConvertor must not be null
Is this the right way to write test cases. can we have code coverage without using thenCallRealMethod()
?
Please suggest me how to proceed. Thanks in advance.
Make sure you have an implementation of the service i.e. TestServiceImpl
annotated with @Service
(or @Component
if it is not strictly a service) and use spying instead of mocking:
@SpyBean
TestService testService;
Spying by default call real methods so you have to mock these that implementation you do not want to call.
Regarding repositories, you should mock the components annotated with @Repository
, not the actual SessionFactory
/ Template
etc. that are used within.