51Testing软件测试论坛

标题: 分享Mockito单元测试利器使用方式(三) [打印本页]

作者: lsekfe    时间: 2023-3-27 14:05
标题: 分享Mockito单元测试利器使用方式(三)
三、学习了这么多,牛刀小试一下!
  测试实体类:
  @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.mo ... ockito/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 ... r-captor-annotation
  利用ArgumentCaptor(参数捕获器)捕获方法参数进行验证:https://www.iteye.com/blog/hotdog-916364
  改变mock返回值:https://www.huangyunkun.com/2014 ... eep-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 ... _relevant.none-task
  测试覆盖率无法统计解决:https://blog.csdn.net/zhanglei082319/article/details/81536398








欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2