前言
在Spring单元测试中,如果不想生成的对象受Spring管理的话,就可以使用Mock注解,为了减少单测与spring框架的耦合,并且尽量不使用真实对象进行模拟,可以使用@InjectMocks和@Mock注解
Mockito使用
生成@Mock、@Spy备注的mock对象,用
typescript
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
定义一个实体类
vbnet
@Data
public class UserQuery {
private Long id;
private String account;
private String username;
private Long deptId;
private List<Long> roleIds;
private String password;
}
定义一个service接口
scss
public Boolean save(UserQuery userQuery) {
UserDTO userDTO = new UserDTO();
userDTO.setUsername(userQuery.getAccount());
R<Boolean> result = remoteUserAdminService.isExist(userDTO);
if (!Objects.equals(result.getCode(), CommonConstants.SUCCESS)) {
throw new BussException("判断用户名是否存在错误");
}
if (result.getData()) {
throw new BussException("用户名已存在");
}
userDTO.setNickName(userQuery.getUsername());
result = remoteUserAdminService.user(userDTO);
if (!Objects.equals(result.getCode(), CommonConstants.SUCCESS)) {
throw new BussException("保存用户异常");
}
return result.getData();
}
测试单元如下
scss
@DisplayName("用户模块测试")
public class UserServiceImplTest {
@InjectMocks
private UserServiceImpl userService;
@Mock
private RemoteUserService remoteUserService;
@Mock
private RemoteUserAdminService remoteUserAdminService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Nested
@DisplayName("新建用户单元测试")
public class UserAddTest {
@Test
@DisplayName("保存用户,查询用户名是否存在,三方系统返回调用失败 => 返回异常")
void save_1_test() {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
UserDTO userDTO = new UserDTO();
userDTO.setUsername(userQuery.getAccount());
R<Boolean> result = R.restResult(null, 1, "操作失败");
Mockito.when(remoteUserAdminService.isExist(Mockito.any(UserDTO.class))).thenReturn(result);
Assertions.assertThrows(BussException.class, () -> {
userService.save(userQuery);
});
Mockito.verify(remoteUserAdminService, times(1)).isExist(Mockito.any(UserDTO.class));
}
@Test
@DisplayName("保存用户,查询用户名是否存在,三方系统返回用户名已经存在 => 返回异常")
void save_2_test() {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
UserDTO userDTO = new UserDTO();
userDTO.setUsername(userQuery.getAccount());
R<Boolean> result = R.restResult(true, 0, "操作成功");
Mockito.when(remoteUserService.isExist(Mockito.any(UserDTO.class))).thenReturn(result);
Assertions.assertThrows(BussException.class, () -> {
userService.save(userQuery);
});
Mockito.verify(remoteUserService, times(1)).isExist(Mockito.any(UserDTO.class));
}
@Test
@DisplayName("保存用户,三方系统返回保存异常 => 返回异常")
void save_3_test() {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
UserDTO userDTO = new UserDTO();
userDTO.setUsername(userQuery.getAccount());
R<Boolean> result = R.restResult(false, 0, "操作成功");
Mockito.when(remoteUserService.isExist(Mockito.any(UserDTO.class))).thenReturn(result);
R<Boolean> saveR = R.restResult(false, 1, "操作失败");
Mockito.when(remoteUserService.user(Mockito.any(UserDTO.class))).thenReturn(saveR);
Assertions.assertThrows(BussException.class, () -> {
userService.save(userQuery);
});
Mockito.verify(remoteUserService, times(1)).isExist(Mockito.any(UserDTO.class));
Mockito.verify(remoteUserService, times(1)).user(Mockito.any(UserDTO.class));
}
@Test
@DisplayName("保存用户,三方系统返回成功 => 保存用户成功")
void save_4_test() {
UserQuery userQuery = new UserQuery();
userQuery.setUsername("aa");
UserDTO userDTO = new UserDTO();
userDTO.setUsername(userQuery.getAccount());
R<Boolean> result = R.restResult(false, 0, "操作成功");
Mockito.when(remoteUserService.isExist(Mockito.any(UserDTO.class))).thenReturn(result);
R<Boolean> saveR = R.ok(true, "操作成功");
Mockito.when(remoteUserService.user(Mockito.any(UserDTO.class))).thenReturn(saveR);
Boolean isSuccess = userService.save(userQuery);
Mockito.verify(remoteUserService, times(1)).isExist(Mockito.any(UserDTO.class));
Mockito.verify(remoteUserService, times(1)).user(Mockito.any(UserDTO.class));
Assertions.assertTrue(isSuccess);
}
}
}
其中
Mockito.when
Mockito.when是模拟一个方法返回值,如
ini
Mockito.when(remoteUserService.isExist(Mockito.any(UserDTO.class))).thenReturn(result);
R<Boolean> saveR = R.ok(true, "操作成功");
模拟方法中调用isExist,返回result结果,Mockito.any(UserDTO.class)是传入一个UserDTO值
Mockito.verify
Mockito.verify(remoteUserService, times(1)),是验证方法中remoteUserService是不是被被用了一次
总结
在单元测试中,Mockito可以模拟出对象不受Spring框架影响,这样在没有Bean的注入和管理下,启动和验证就比较快,当然,写单元测试的时候,具体问题具体分析