三、学习了这么多,牛刀小试一下!
测试实体类:
@Data
public class User {
/**
* 姓名,登录密码
*/
持久层 DAO:
public interface UserDao {
/**
* 根据name查找user
* @param name
* @return
*/
User getUserByName(String name);
/**
* 保存user
* @param user
* @return
*/
Integer saveUser(User user);
}
业务层 Service 接口:
public interface UserService {
/**
* 根据name查找user
* @param name
* @return
*/
User getUserByName(String name);
/**
* 保存user
* @param user
* @return
*/
Integer saveUser(User user);
}
业务层 Serive 实现类:
@Service
public class UserServiceImpl implements UserService {
//userDao
@Autowired
private UserDao userDao;
/**
* 根据name查找user
* @param name
* @return
*/
@Override
public User getUserByName(String name) {
try {
return userDao.getUserByName(name);
} catch (Exception e) {
throw new RuntimeException("查询user异常");
}
}
/**
* 保存user
* @param user
* @return
*/
@Override
public Integer saveUser(User user) {
if (userDao.getUserByName(user.getName()) != null) {
throw new RuntimeException("用户名已存在");
}
try {
return userDao.saveUser(user);
} catch (Exception e) {
throw new RuntimeException("保存用户异常");
}
}
}
现在我们的 Service 写好了,想要单元测试一下,但是 Dao 是其他人开发的,目前还没有写好,那我们如何测试呢?
public class UserServiceTest {
/**
* Mock测试:根据name查询user
*/
@Test
public void getUserByNameTest() {
// mock对象
final UserDao userDao = mock(UserDao.class);
final UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(userDao);
// stub调用
final User user = new User();
user.setName("admin");
user.setPassword("pass");
when(userDao.getUserByName("admin")).thenReturn(user);
// 执行待测试方法
final User user1 = userService.getUserByName("admin");
System.out.println("查询结果:" + JacksonUtil.obj2json(user1)); //查询结果:{"name":"admin","password":"pass"}
// 验证mock对象交互
verify(userDao).getUserByName(anyString());
// 验证查询结果
Assert.assertNotNull("查询结果为空!", user1);
Assert.assertEquals("查询结果错误!", "admin", user1.getName());
}
/**
* Mock测试:保存user
*/
@Mock
private UserDao userDao;
@InjectMocks
private UserServiceImpl userService;
@Test
public void saveUserTest() throws Exception{
// 执行注解初始化
MockitoAnnotations.initMocks(this);
// mock对象stub操作
final User user = new User();
user.setName("admin");
user.setPassword("pass");
when(userDao.getUserByName("admin")).thenReturn(user).thenReturn(null);
when(userDao.saveUser(any(User.class))).thenReturn(1);
// 验证用户名重复的情况
try {
userService.saveUser(user);
throw new Exception(); //走到这里说明验证失败
} catch (RuntimeException e) {
System.out.println("重复用户名保存失败-测试通过"); //重复用户名保存失败-测试通过
}
verify(userDao).getUserByName("admin");
// 验证正常保存的情况
user.setName("user");
final Integer integer = userService.saveUser(user);
System.out.println("保存结果:" + integer); //保存结果:1
Assert.assertEquals("保存失败!", 1, integer.longValue());
verify(userDao).saveUser(any(User.class));
verify(userDao, times(2)).getUserByName(anyString());
}
}
根据以上代码我们可以知道,当我们的待测类开发完成而依赖的类的实现还没有开发完成。此时,我们就可以用到我们的 Mock 测试,模拟我们依赖类的返回值,使我们的待测类与依赖类解耦。这样,我们就可以对我们的待测类进行单元测了。
四、参考文档及进一步学习~
Mockito英文版javadoc:https://javadoc.io/static/org.mockito/mockito-core/3.3.3/org/mockito/Mockito.html
Mockito中文文档(部分):https://blog.csdn.net/bboyfeiyu/article/details/52127551#35
Mockito使用教程:https://www.cnblogs.com/Ming8006/p/6297333.html
参数捕获器使用:https://www.journaldev.com/21892/mockito-argumentcaptor-captor-annotation
利用ArgumentCaptor(参数捕获器)捕获方法参数进行验证:https://www.iteye.com/blog/hotdog-916364
改变mock返回值:https://www.huangyunkun.com/2014/10/25/mockito-deep-stub-with-enum/
五分钟了解Mockito:https://www.iteye.com/blog/liuzhijun-1512780
使用Mockito进行单元测试:https://www.iteye.com/blog/qiuguo0205-1443344
JUnit + Mockito 单元测试:https://blog.csdn.net/zhangxin09/article/details/42422643
Mockito中@Mock与@InjectMock:https://www.cnblogs.com/langren1992/p/9681600.html
mockito中两种部分mock的实现,spy、callRealMethod:https://www.cnblogs.com/softidea/p/4204389.html
Mockito 中被 Mocked 的对象属性及方法的默认值:https://www.cnblogs.com/fnlingnzb-learner/p/10635250.html
单元测试工具之Mockito:https://blog.csdn.net/qq_32140971/article/details/90598454
引入Mockito测试用@Spy和@Mock:https://blog.csdn.net/message_lx/article/details/83308114
Mockito初探(含实例):https://www.iteye.com/blog/sgq0085-2031319
测试覆盖率统计:https://blog.csdn.net/lvyuan1234/article/details/82836052?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
测试覆盖率无法统计解决:https://blog.csdn.net/zhanglei082319/article/details/81536398
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理