如何使用 mockito 和 junit 来测试我的 spring boot rest api?
how to use mockito and junit to test my spring boot rest api?
我是单元测试的新手,不知道如何使用 Mockito 和 Junit 测试 RESTFul API 和 Spring,首先我已经准备好 class 其中我用 @Before 和 @Test 创建了两个方法,当我进入调试模式时它告诉我 hasSize 集合 return 0 不是 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);
}
}
这里是 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;
}
}
当我进入调试模式时,它告诉我有NullPointerException
。
如何正确使用mockito
和junit
才能通过考试?
我发现了一些潜在的问题:
首先,您正在呼叫
List<Employe> listemp=employeService.findAllEmployeActive();
在您的控制器的 getEmployeDTOList()
中,但是您的 Mockito 模拟写为:
when(employeService.findAll()).thenReturn(employes)
因此,您的测试可能无法正常工作,因为您的模拟从未发生过。
其次,您没有嘲笑您在控制器中自动装配的 ModelMapper
。我 认为 Spring 仍会继续为您获取该组件(如果我在那里错了,请有人纠正我),但无论哪种方式,拥有您的单位都不是很好的做法测试依赖于外部库,因为您应该只关心控制器的功能。最好模拟 ModelMapper
使其 "always" 工作并编写单独的测试来验证您的映射。
我继续制作我自己的代码版本来测试。我将 hasSize
更改为 2 因为您在示例中只使用了两个元素。
这个测试对我有用:
@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);
}
}
如您所见,我创建了自己的 DTO 对象并将它们传回,这样 modelMapper
将始终按预期进行此单元测试。
这是有效的代码,但它忽略了对象 emp1:
public void testgetAllEmployeeWithModelMapper() throws Exception{
Employe emp1 = new Employe("Hamza", "Khadhri", "hamza1007", "123");
Employe emp2 = new Employe("Oussem", "smi", "oussama", "1234");
List<Employe> Employees= Arrays.asList(emp1, emp2);
EmployeDTO dto1 = new EmployeDTO("Hamza", "Khadhri", "hamza1007", "123");
EmployeDTO dto2 = new EmployeDTO("Oussem", "smi", "oussama", "1234");
when(modelMapper.map(emp1,EmployeDTO.class)).thenReturn(dto1);
when(modelMapper.map(emp2,EmployeDTO.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);
}
}
控制台显示 jsonPath("$[0].nom" 期望 Oussema
因此,当我将其更改为对象 emp2 的 Oussema 时,它运行良好。不幸的是,它忽略了包含 Hamza 的对象 emp1,
个人而言,我只是在 Employe 和 EmployeDTO 中添加了两个构造函数。
这是 class 员工:
public class Employe implements Serializable {
@Id
@Column(unique=true, nullable=false, precision=6)
private Long id;
@Column(precision=6)
private BigDecimal cv;
@Column(length=254)
private String nom;
@Column(length=254)
private String prenom;
@Column(length=254)
private String login;
@Column(length=254)
private String mp;
@Column(length=254)
private String mail;
@Column(precision=6)
private BigDecimal idpointage;
@Column(length=1)
private Boolean actif;
public Employe(String nom, String prenom, String login, String mp) {
this.nom = nom;
this.prenom = prenom;
this.login = login;
this.mp = mp;
}
这是 class EmployeDTO:
public class EmployeDTO {
private String nom;
private String prenom;
private String login ;
private String mp ;
public EmployeDTO(String nom, String prenom, String login, String mp) {
this.nom= nom ;
this.prenom= prenom ;
this.login = login ;
this.mp=mp ;
}
我是单元测试的新手,不知道如何使用 Mockito 和 Junit 测试 RESTFul API 和 Spring,首先我已经准备好 class 其中我用 @Before 和 @Test 创建了两个方法,当我进入调试模式时它告诉我 hasSize 集合 return 0 不是 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);
}
}
这里是 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;
}
}
当我进入调试模式时,它告诉我有NullPointerException
。
如何正确使用mockito
和junit
才能通过考试?
我发现了一些潜在的问题:
首先,您正在呼叫
List<Employe> listemp=employeService.findAllEmployeActive();
在您的控制器的 getEmployeDTOList()
中,但是您的 Mockito 模拟写为:
when(employeService.findAll()).thenReturn(employes)
因此,您的测试可能无法正常工作,因为您的模拟从未发生过。
其次,您没有嘲笑您在控制器中自动装配的 ModelMapper
。我 认为 Spring 仍会继续为您获取该组件(如果我在那里错了,请有人纠正我),但无论哪种方式,拥有您的单位都不是很好的做法测试依赖于外部库,因为您应该只关心控制器的功能。最好模拟 ModelMapper
使其 "always" 工作并编写单独的测试来验证您的映射。
我继续制作我自己的代码版本来测试。我将 hasSize
更改为 2 因为您在示例中只使用了两个元素。
这个测试对我有用:
@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);
}
}
如您所见,我创建了自己的 DTO 对象并将它们传回,这样 modelMapper
将始终按预期进行此单元测试。
这是有效的代码,但它忽略了对象 emp1:
public void testgetAllEmployeeWithModelMapper() throws Exception{
Employe emp1 = new Employe("Hamza", "Khadhri", "hamza1007", "123");
Employe emp2 = new Employe("Oussem", "smi", "oussama", "1234");
List<Employe> Employees= Arrays.asList(emp1, emp2);
EmployeDTO dto1 = new EmployeDTO("Hamza", "Khadhri", "hamza1007", "123");
EmployeDTO dto2 = new EmployeDTO("Oussem", "smi", "oussama", "1234");
when(modelMapper.map(emp1,EmployeDTO.class)).thenReturn(dto1);
when(modelMapper.map(emp2,EmployeDTO.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);
}
}
控制台显示 jsonPath("$[0].nom" 期望 Oussema 因此,当我将其更改为对象 emp2 的 Oussema 时,它运行良好。不幸的是,它忽略了包含 Hamza 的对象 emp1, 个人而言,我只是在 Employe 和 EmployeDTO 中添加了两个构造函数。
这是 class 员工:
public class Employe implements Serializable {
@Id
@Column(unique=true, nullable=false, precision=6)
private Long id;
@Column(precision=6)
private BigDecimal cv;
@Column(length=254)
private String nom;
@Column(length=254)
private String prenom;
@Column(length=254)
private String login;
@Column(length=254)
private String mp;
@Column(length=254)
private String mail;
@Column(precision=6)
private BigDecimal idpointage;
@Column(length=1)
private Boolean actif;
public Employe(String nom, String prenom, String login, String mp) {
this.nom = nom;
this.prenom = prenom;
this.login = login;
this.mp = mp;
}
这是 class EmployeDTO:
public class EmployeDTO {
private String nom;
private String prenom;
private String login ;
private String mp ;
public EmployeDTO(String nom, String prenom, String login, String mp) {
this.nom= nom ;
this.prenom= prenom ;
this.login = login ;
this.mp=mp ;
}