文档章节

对代码更有信心--单元测试工具Mockito简单介绍

zgw06629
 zgw06629
发布于 2015/04/27 12:03
字数 1064
阅读 425
收藏 7
点赞 0
评论 0

许多同事怕写单元测试的一个主要原因(或借口)就是依赖太多(redis,mysql,webservice等)。但其实可以用Mockito来模拟相关行为,不用费力去准备各种依赖环境,这时只需专注于业务逻辑即可。

比如有这么一个业务需求,若用户已经购买了容量(20GB,200GB),直接返回容量,若未购买,再判断该用户是否存在,若不存在,提示该用户不存在;若存在则判断是否为激活用户,若为激活用户返回2GB, 若为非激活用户返回1GB。

controller代码如下:

@Autowired
private StorageService storageService;
@Autowired
private UserService userService;
@RequestMapping({ "/storage/userId/{userId}" })
@ResponseBody
public CommonResultDTO getUserStorage(@PathVariable("userId") String userId){
    CommonResultDTO result = new CommonResultDTO();
    Integer capacity = storageService.getUserStorage(userId); //查询用户是否购买了容量
     
    if(capacity==null){ //没有购买
        User user = userService.getUser(userId); //查询该用户
        if(user==null){ //用户不存在
            result.setStatus(FAILURE_STATUS);
            result.setMessage(USER_NOT_EXIST);
        }
        else if(user.getStatus()==ACTIVE) //激活用户 默认返回2GB
            capacity = DEFAULT_ACTIVE_USER_CAPACITY;
        else if(user.getStatus() == INACTIVE) //未激活用户 默认返回1GB
            capacity = DEFAULT_INACTIVE_USER_CAPACITY;
    }
    result.setData(capacity);
    return result;
}

假如只想测试上述业务逻辑,而不想费力去开启本地数据库,并准备各种数据,如插入一条用户购买记录(insert user_storage (user_id, product_id) values(1, 1)),插入一个激活用户(insert into user(user_id, status) values(1, 0)),一个非激活用户。若上述业务还用到了缓存,那准备的工作就更多了.。估计此时大部分开发人员已经打消了写单元测试的念头了,并祈祷这段代码能平平安安。

于是轻易地就把命运交给老天了。

幸好有了Mockito框架,命运又可以掌握在自己手中了,它提供了易用的Api可以让我们仅需关注主要业务逻辑而无需耗费精力在准备繁琐的测试环境上。

见如下示例代码:

@RunWith(MockitoJUnitRunner.class)
public class StorageControllerTest {
    @InjectMocks
    private StorageController controller;
    @Mock
    private UserService userService;
    @Mock
    private StorageService storageService;
    @Test
    public void test_user_not_exist(){
        //1. 验证用户不存在
        String userId = "notexist";
        // 当执行storageService.getUserStorage(userId)时直接返回空 表示未购买
        Mockito.when(storageService.getUserStorage(userId)).thenReturn(null);
        // 当执行userService.getUser(userId)时 返回空 表示用户不存在
        Mockito.when(userService.getUser(userId)).thenReturn(null);
         
        CommonResultDTO result = controller.getUserStorage(userId);
        Assertions.assertThat(result.getStatus()).isEqualTo(FAILURE_STATUS);
        Assertions.assertThat(result.getMessage()).isEqualTo(USER_NOT_EXIST);
        //验证是否执行了storageService.getUserStorage(userId)一次;
        Mockito.verify(storageService).getUserStorage(userId);
        //验证是否执行了userService.getUser(userId)一次;
        Mockito.verify(userService).getUser(userId);
    }
    @Test
    public void test_inactive_and_not_buy_user_storage(){
        //2. 验证未购买且未激活用户的返回容量
        // 定义一未激活状态用户
        String userId = "1";
        User user = new User();
        user.setStatus(INACTIVE);
        // 当执行storageService.getUserStorage(userId)时直接返回空 表示未购买
        Mockito.when(storageService.getUserStorage(userId)).thenReturn(null);
        // 当执行userService.getUser(userId)时 返回上面定义的未激活状态User
        Mockito.when(userService.getUser(userId)).thenReturn(user);
         
        CommonResultDTO result = controller.getUserStorage(userId);
        Assertions.assertThat(result.getData()).isEqualTo(DEFAULT_INACTIVE_USER_CAPACITY);
        //验证是否执行了storageService.getUserStorage(userId);
        Mockito.verify(storageService).getUserStorage(userId);
        //验证是否执行了userService.getUser(userId);
        Mockito.verify(userService).getUser(userId);
    }
    @Test
    public void test_active_and_not_buy_user_storage(){
        //3. 验证未购买但激活用户的返回容量
        // 定义一激活状态用户对象
        String userId = "1";
        User user = new User();
        user.setStatus(ACTIVE);
        // 当执行storageService.getUserStorage(userId)时直接返回空 表示未购买
        Mockito.when(storageService.getUserStorage(userId)).thenReturn(null);
        // 当执行userService.getUser(userId)时 返回上面定义的激活状态User
        Mockito.when(userService.getUser(userId)).thenReturn(user);
         
        CommonResultDTO result = controller.getUserStorage(userId);
        Assertions.assertThat(result.getData()).isEqualTo(DEFAULT_ACTIVE_USER_CAPACITY);
        //验证是否执行了storageService.getUserStorage(userId);
        Mockito.verify(storageService).getUserStorage(userId);
        //验证是否执行了userService.getUser(userId);
        Mockito.verify(userService).getUser(userId);
    }
    @Test
    public void test_had_bought_user_storage(){
        //4. 验证已购买用户的返回容量
        String userId = "1";
        // 当执行storageService.getUserStorage(userId)时直接返回20 表示用户购买了20GB的容量
        final int CAPACITY_20 = 20;
        Mockito.when(storageService.getUserStorage(userId)).thenReturn(CAPACITY_20);
         
        CommonResultDTO result = controller.getUserStorage(userId);
        Assertions.assertThat(result.getData()).isEqualTo(CAPACITY_20);
        //验证是否执行了storageService.getUserStorage(userId);
        Mockito.verify(storageService).getUserStorage(userId);
        //用户已购买的情况下 不会执行userService.getUser(userId) 故此处设置times(0) 表示未执行
        Mockito.verify(userService,Mockito.times(0)).getUser(userId);
    }
}

无需依赖外部环境,只须通过Mockito.when().thenReturn()来准备各种待测条件下的数据(如用户不存在、激活用户、非激活用户等)。

我想若通过了上面这个逻辑严密的测试,对这段代码应该是格外有信心了吧。不用每天在胸前画十字了。

见测试结果:

补充:

Mockito maven 坐标

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.9.5</version>
</dependency>


© 著作权归作者所有

共有 人打赏支持
zgw06629
粉丝 15
博文 54
码字总数 30471
作品 0
海淀
程序员
Kotlin 写 Android 单元测试(三),Mockito mocking 框架的使用

Kotlin 写 Android 单元测试系列: Kotlin 写 Android 单元测试(一),单元测试是什么以及为什么需要 Kotlin 写 Android 单元测试(二),JUnit 4 测试框架和 kotlin.test 库的使用 Kotlin...

JohnnyShieh
2017/12/14
0
0
Mockito入门及配合Junit进行单元测试

声明:原创文章,转载请注明出处。http://www.jianshu.com/p/46afe8c54d34 一、背景 最近一段时间在给写的框架补单元测试。发现有一些方法做单元测试不好做,主要是其内部依赖了许多外部环境...

唐影若凡
2017/11/17
0
0
【腾讯Bugly干货分享】安卓单元测试:What, Why and How

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d28349101cd07a5404c415 Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员...

腾讯Bugly
2016/09/26
20
0
【腾讯Bugly干货分享】安卓单元测试:What, Why and How

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d28349101cd07a5404c415 Dev Club 是一个交流移动开发技术,结交朋友,扩展人脉的社群,成员...

腾讯Bugly
2016/10/10
488
0
自动化单元测试实践之路

info已经发布: http://www.infoq.com/cn/articles/road-of-automated-unit-testing-practices 自动化单元测试并不是什么新鲜事物,它应该是团队持之以恒的事情,可能有很多团队知道如何去做...

jooben
2014/05/12
0
0
提升单元测试体验的利器--Mockito使用总结

为神马要使用Mockito?   在编写单元测试的时候,为了尽可能的保证隔离性,我们时常需要对某些不容易构造或者不容易获取或者对外部环境有依赖的对象,用一个虚拟的对象来创建以便于测试.假设你...

冬至饮雪
2017/06/06
0
0
用PowerMock进行Android单元测试与BDD行为驱动开发

很久之前就有听说过mockito和PowerMock的大名了,无奈我司写单元测试的风气不浓,加上一直以来业务繁忙,惰性使我一直没有写单元测试的习惯。 正好现在手头上的是一个全新的项目,可以在初期有时...

嘉伟咯
2017/08/26
0
0
[Android技术专题]每个开发者都应该懂一点单元测试

为了方便在手机上阅读,文章也会在公众号发出,更多原创文章和优质资源请关注公众号: 公众号:open_dev 更多Android技术资源交流请加群“Android技术资源交流群”,第1期群分享精华已在微信...

张明云
2016/08/27
0
0
Mockito 简明教程

原文同步至 Mock 测试是单元测试的重要方法之一。本文介绍了基于 Java 语言的 Mock 测试框架 -- Mockito 的使用。 什么是 Mock 测试 Mock 测试就是在测试过程中,对于某些不容易构造(如 Ht...

waylau
2016/02/19
244
2
Java EE 单元测试

觉得测试 Java EE 应用程序太困难、不方便或者太复杂?通过阅读本文,您将了解现实情况并非如此,同时还将了解如何高效进行单元测试。 测试是 Java Platform, Enterprise Edition (Java EE) ...

justjavac
2013/09/12
443
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

实现异步有哪些方法

有哪些方法可以实现异步呢? 方式一:java 线程池 示例: @Test public final void test_ThreadPool() throws InterruptedException { ScheduledThreadPoolExecutor scheduledThre......

黄威
今天
0
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

六库科技
今天
0
0
牛客网刷题

1. 二维数组中的查找(难度:易) 题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入...

大不了敲一辈子代码
今天
0
0
linux系统的任务计划、服务管理

linux任务计划cron 在linux下,有时候要在我们不在的时候执行一项命令,或启动一个脚本,可以使用任务计划cron功能。 任务计划要用crontab命令完成 选项: -u 指定某个用户,不加-u表示当前用...

黄昏残影
昨天
0
0
设计模式:单例模式

单例模式的定义是确保某个类在任何情况下都只有一个实例,并且需要提供一个全局的访问点供调用者访问该实例的一种模式。 实现以上模式基于以下必须遵守的两点: 1.构造方法私有化 2.提供一个...

人觉非常君
昨天
0
0
《Linux Perf Master》Edition 0.4 发布

在线阅读:https://riboseyim.gitbook.io/perf 在线阅读:https://www.gitbook.com/book/riboseyim/linux-perf-master/details 百度网盘【pdf、mobi、ePub】:https://pan.baidu.com/s/1C20T......

RiboseYim
昨天
1
0
conda 换源

https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/conda config --add channels https://mir......

阿豪boy
昨天
1
0
Confluence 6 安装补丁类文件

Atlassian 支持或者 Atlassian 缺陷修复小组可能针对有一些关键问题会提供补丁来解决这些问题,但是这些问题还没有放到下一个更新版本中。这些问题将会使用 Class 类文件同时在官方 Jira bug...

honeymose
昨天
0
0
非常实用的IDEA插件之总结

1、Alibaba Java Coding Guidelines 经过247天的持续研发,阿里巴巴于10月14日在杭州云栖大会上,正式发布众所期待的《阿里巴巴Java开发规约》扫描插件!该插件由阿里巴巴P3C项目组研发。P3C...

Gibbons
昨天
1
0
Tomcat介绍,安装jdk,安装tomcat,配置Tomcat监听80端口

Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache、Sun和其他一些公司及个人共同开发而成。 java程序写的网站用tomcat+jdk来运行...

TaoXu
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部