I'm new in unit testing and cannot figure out how to test the RESTFul API with Spring using Mockito and Junit, first of all i have preapared the class in which i created two method with @Before and @Test, when i turned in debugging mode it tells me that hasSize collection return 0 not 4.
@RunWith(SpringJUnit4ClassRunner.class)
public class EmployeControllerTest {
private MockMvc mockMvc;
@InjectMocks
private EmployeController employeController ;
@Mock
private EmployeService employeService ;
@Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
mockMvc=MockMvcBuilders.standaloneSetup(employeController).build();
}
@Test
public void testgetAllEmployee() throws Exception{
List<Employe> employes= Arrays.asList(
new Employe("Hamza", "Khadhri", "hamza1007", "123")
,new Employe("Oussema", "smi", "oussama", "1234") );
when(employeService.findAll()).thenReturn(employes);
mockMvc.perform(get("/employe/dto"))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$", hasSize(4)))
.andExpect(jsonPath("$[0].nom", is("Hamza")))
.andExpect(jsonPath("$[0].prenom", is("Khadhri")))
.andExpect(jsonPath("$[0].login", is("hamza1007")))
.andExpect(jsonPath("$[0].mp", is("123")))
.andExpect(jsonPath("$[1].nom", is("Oussema")))
.andExpect(jsonPath("$[1].prenom", is("smi")))
.andExpect(jsonPath("$[1].login", is("oussama")))
.andExpect(jsonPath("$[1].mp", is("1234")));
verify(employeService,times(1)).findAll();
verifyNoMoreInteractions(employeService);
}
}
here is the EmployeController :
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
@RequestMapping("/employe")
public class EmployeController {
@Autowired
private EmployeService employeService;
@Autowired
private ModelMapper modelMapper;
@GetMapping("/dto")
public List<EmployeDTO> getEmployeDTOList(){
try {
List<Employe> listemp=employeService.findAllEmployeActive();
return listemp.stream()
.map(emp ->convertToDto(emp))
.collect(Collectors.toList());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private EmployeDTO convertToDto(Employe emp) {
EmployeDTO empDto = modelMapper.map(emp, EmployeDTO.class);
return empDto;
}
}
when I turn in debugging mode, it tells me that there is NullPointerException
.
How to use properly mockito
and junit
to succeed the test?
I see a few potential issues:
First, you are calling
List<Employe> listemp=employeService.findAllEmployeActive();
in your controller's getEmployeDTOList()
, but your Mockito mock is written as:
when(employeService.findAll()).thenReturn(employes)
So, your test might not be working simply because your mock never happens.
Second, you have not mocked the ModelMapper
that you autowired in your controller. I think Spring will still go ahead and grab that component for you (someone correct me if I'm wrong there), but either way it's not great practice to have your unit tests be dependent on external libraries since you should only be concerned with the controller's functionality. It would be better to mock ModelMapper
to make it "always" work and write separate tests to validate your mappings.
I went ahead and made my own version of your code to test things out. I changed hasSize
to 2 because you were only using two elements in your example.
This test is working for me:
@RunWith(SpringJUnit4ClassRunner.class)
public class EmployeeControllerTest {
private MockMvc mockMvc;
@InjectMocks
private EmployeeController employeeController ;
@Mock
private EmployeeService employeeService;
@Mock
private ModelMapper modelMapper;
@Before
public void setUp() throws Exception{
MockitoAnnotations.initMocks(this);
mockMvc=MockMvcBuilders.standaloneSetup(employeeController).build();
}
@Test
public void testgetAllEmployeeWithModelMapper() throws Exception{
Employee emp1 = new Employee("Hamza", "Khadhri", "hamza1007", "123");
Employee emp2 = new Employee("Oussema", "smi", "oussama", "1234");
List<Employee> Employees= Arrays.asList(emp1, emp2);
EmployeeDTO dto1 = new EmployeeDTO("Hamza", "Khadhri", "hamza1007", "123");
EmployeeDTO dto2 = new EmployeeDTO("Oussema", "smi", "oussama", "1234");
when(modelMapper.map(emp1,EmployeeDTO.class)).thenReturn(dto1);
when(modelMapper.map(emp2,EmployeeDTO.class)).thenReturn(dto2);
when(employeeService.findAll()).thenReturn(Employees);
mockMvc.perform(get("/employe/dto"))
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON_UTF8_VALUE))
.andExpect(jsonPath("$", hasSize(2)))
.andExpect(jsonPath("$[0].nom", is("Hamza")))
.andExpect(jsonPath("$[0].prenom", is("Khadhri")))
.andExpect(jsonPath("$[0].login", is("hamza1007")))
.andExpect(jsonPath("$[0].mp", is("123")))
.andExpect(jsonPath("$[1].nom", is("Oussema")))
.andExpect(jsonPath("$[1].prenom", is("smi")))
.andExpect(jsonPath("$[1].login", is("oussama")))
.andExpect(jsonPath("$[1].mp", is("1234")));
verify(employeeService,times(1)).findAll();
verifyNoMoreInteractions(employeeService);
}
}
As you can see I create my own DTO objects and pass them back so that modelMapper
will always behave as expected for this unit test.