文章插图
为什么要mock?有很多朋友不愿意写单元测试 , 觉得写单测试比较花时间 , 甚至不会写单元测试 , 很大程度上是因为不想写或者不会写mock 。
mock对于单元测试来很重要 。单元测试之所以名字里面有“单元” , 就是因为一个测试用例只测很小的一个单元代码 。但我们的代码总会有依赖 , 要测试的方法内部可能调用了其它类的方法 , 这在代码中是很常见的逻辑 。所以我们经常会需要mock , 用来消除依赖 。
所谓mock , 翻译过来就是“模拟” , 就是模拟你要测试的代码里面「依赖的其它对象」 , 模拟它的输入和输出 , 这样就不用管其它逻辑是如何实现的 , 我们「假定它是符合我们期望的就行了」 。
可能你会有一个疑问:那我们在单元测试里面假定它符合期望了 , 但实际运行时它有bug了 , 并不是符合我们期望的 , 怎么办呢?
首先 , 我们对那个类也会做单元测试 , 我们用它的单元测试保证了它的逻辑是正确的 。
然后 , 一个完整的测试体系 , 不应该只有单元测试 。单元测试之上 , 还应该有集成测试、API测试等 , 从更高的层面来保证整个应用程序能够如预期工作 。
Mockito的基本用法Mockito是JAVA语言非常主流的一个框架 , 自己使用起来感觉也比较好用 。所以这篇文章想汇总介绍一下Mockito的各种用法 , 这样大家在以后写单元测试和看单元测试的时候 , 就能够比较清晰为什么要这么写 。
设置Mockito环境要使用Mockito , 首先得在测试类里面设置好Mockito环境 。这是为了能够让单元测试框架(本文主要介绍JUnit)能够识别和使用Mockito 。
在JUnit 4 , JUnit使用了@RunWith注解来声明一个“运行器” 。这个运行期的作用是为单元测试提供「mock的初始化工作」(比如使用@Mock、@Spy等注解时 , 需要初始化) , 以及「验证mock语法」的功能 。
比如我们可能会经常用到的:
@RunWith(JUnit4.class)@RunWith(SpringRunner.class)@RunWith(SpringJUnit4ClassRunner.class)
Mockito也有相应的启动器 , 在@RunWith注解上面使用这个启动器就可以使用Mockito的环境了:@RunWith(MockitoJUnitRunner)
在JUnit 5 , 使用了@ExtendWith注解来代替@RunWith注解 , Mockito也支持JUnit 5 , 提供了MockitoExtension类 。除了使用注解以外 , 也可以使用静态方法initMocks来实现这个功能:
MockitoAnnotations.initMocks(this)
mockmock , 即mock一个对象 。也是注解和代码两种方式可以实现 。【mockito从入门到通关】
@Mockprivate User user;Order order = Mockito.mock(Order.class);
mock对象后 , 就可以对它使用given等方法模拟它的输入和输出 。given(order.getId()).willReturn(1L);assertEquals(order.getId(), 1L);
spymock出来的对象是完全虚拟的 , 不会真正地调用本来的实现 。如果不对它使用given等方法 , 会返回默认值(null, 0, false等) 。而spy如果不使用given等方法 , 会调用这个对象本来的实现 , 返回实际运行后的值 。?spy同样有注解和静态方法的方式:
不是很推荐使用spy , 因为它没有消除依赖
?
@Spyprivate user user;Order order = Mockito.spy(Order.class);
captorcaptor翻译过来是“捕获”的意思 , 主要用来捕捉程序运行时调用mock或者spy的对象的方法时 , 传入的参数 。它支持泛型 , 即要捕获的参数的类型 。@Captor ArgumentCaptor<User> userCaptor;ArgumentCaptor<String> arg = ArgumentCaptor.forClass(String.class);
captor一般是与given或者verify等方法配合使用 。@MockList mockedList; @Captor ArgumentCaptor argCaptor;@Testpublic void whenUseCaptorAnnotation_thenTheSam() { mockedList.add("one"); Mockito.verify(mockedList).add(argCaptor.capture()); assertEquals("one", argCaptor.getValue());}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 怎么从外观上区分HDMI1.4与HDMI2.0?
- MySQL主从不一致情形与解决方法
- sed 命令快速入门
- 教师|父母眼中的“铁饭碗”,我们应该听从吗?应该认可吗?
- 不买房怎么提取公积金?
- 好茶品质从第步开始,龙润茶十二年如日
- 篮球入门技巧简介
- 高尔夫球入门技巧 高尔夫球入门知识
- 聊聊从RPC到服务治理框架
- Python之爬虫入门教程