使用mock模拟解决测试中依赖问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用mock模拟解决测试中依赖问题相关的知识,希望对你有一定的参考价值。
参考技术A 1、开发移动应用 App,可能后端接口还在开发中,这时 App 的开发因为无法调用后端,很不方便。2、程序会依赖第三方的接口,例如微信支付,在本地开发时不能直接调用。
设置返回值和属性
mock object对象的返回值
methods 具体方法返回值
attribute setting 属性的设置
通过构造方法-传参的方式
多次不同返回值,及顺序
mock_calls是跟踪是否被调用
assert_called_with()是断言是否调用的这个参数
assert_called_once_with()是断言是否只调用一次
对已有的类实例使用patch临时改变返回值
dnd.py
test_dnd.py
单元测试中的应用
shot_tweeter.py
test_shot_tweeter.py
接口测试mock实例
users.py
test_users.py
进行子服务的压力测试方案
1、直接使用线上的后端服务进行压测:优点是近线上状态,代价极小;缺点是线上子服务的稳定性,数据统计,引入脏数据等;
2、部署完整的后端测试环境:优点是与线上隔离;测试结果基本与线上环境一致,测试结果相对准确;缺点是部署成本极高;要保证子服务性能的会造成资源浪费。
3、部署部分子服务:优点是与线上隔离;部署成本相对较小;缺点是测试结果有出入,后端性能可能是瓶颈。
4、使用测试平台mock后端接口数据:优点与线上隔离;缺点是mock平台一般性能较弱,测试结果有出入;mock平台的逻辑规则会有一定的学习成本。(可以通过django写的mock服务)
5、使用nginx cache mock子服务返回内容:优点是与线上隔离;子服务返回内容与线上一致;可保证后端性能不是瓶颈;缺点是必须使用固定的一组请求(请求数量在几万的量级没问题)
6、影表
Mock单元测试
单元测试的思路是在不涉及依赖的情况下测试代码,一般是测试service层的方法,但实际的代码常会涉及到依赖,一个可行的方法就是使用模拟对象来替换依赖对象。
1.使用Mockito生成mock对象
Mockito 是一个流行 mock 框架,可以和JUnit结合起来使用。Mockito 允许你创建和配置 mock 对象。使用Mockito可以明显的简化对外部依赖的测试类的开发。
一般使用 Mockito 需要执行下面三步
-
模拟并替换测试代码中外部依赖。
-
执行测试代码
-
验证测试代码是否被正确的执行
1.1.在maven中添加mockito依赖
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-all</artifactId> <scope>test</scope> </dependency>
1.2.静态引用
如果在代码中静态引用了org.mockito.Mockito.*;
,那你你就可以直接调用静态方法和静态变量而不用创建对象,譬如直接调用 mock() 方法。
1.3.使用 Mockito 创建和配置 mock 对象
Mockito 还支持通过 @Mock
注解的方式来创建 mock 对象
使用注解,那么必须要实例化 mock 对象。Mockito 在遇到使用注解的字段的时候,会调用MockitoAnnotations.initMocks(this)
来初始化该 mock 对象。另外也可以通过使用@RunWith(MockitoJUnitRunner.class)
来达到相同的效果。
注解
- @Mock:创建 mock 对象
- @InjectMocks 在 Mockito 中进行依赖注入
调用方法:
when(…?.).thenReturn(…?.)可以被用来定义当条件满足时函数的返回值,如果你需要定义多个返回值,可以多次定义。当你多次调用函数的时候,Mockito 会根据你定义的先后顺序来返回返回值。Mocks 还可以根据传入参数的不同来定义不同的返回值。譬如说你的函数可以将anyString 或者 anyInt作为输入参数,然后定义其特定的放回值。
自定义方法的返回值
Mockito.when(方法).thenReturn(返回值)
Mockito.when(方法).thenReturn(返回值1).thenReturn(返回值2)
无返回值
对于无返回值的函数,我们可以使用doReturn(…?).when(…?).methodCall来获得类似的效果。例如我们想在调用某些无返回值函数的时候抛出异常,那么可以使用doThrow 方法。如下面代码片段所示
Mockito.doThrow(new IOException()).when(mockStream).close()
仅调用方法,但啥也不做
Mockito.doNothing().when(tagRepository).deleteByTagId(1)
验证 query 方法是否被 MyDatabase 的 mock 对象调用
verify(databaseMock).query("* from t");
查看在传入参数为12的时候方法是否被调用
verify(test).testing(Matchers.eq(12));
方法是否被调用两次
verify(test, times(2)).getUniqueId();
verify(mock, never()).someMethod("never called");
verify(mock, atLeastOnce()).someMethod("called at least once");
verify(mock, atLeast(2)).someMethod("called at least twice");
verify(mock, times(5)).someMethod("called five times");
verify(mock, atMost(3)).someMethod("called at most 3 times");
1.4.mockito的限制
下面三种数据类型则不能够被测试
-
final classes
-
anonymous classes
-
primitive types
Mockito 不能够 mock 静态方法,因此我们可以使用 Powermock
2.powerMock
powerMock能mock静态、final、私有方法等
PowerMock支持EasyMock和Mockito。
2.1PowerMock有两个重要的注解:
–@RunWith(PowerMockRunner.class)
–@PrepareForTest( { YourClassWithEgStaticMethod.class })
如果你的测试用例里没有使用注解@PrepareForTest,那么可以不用加注解@RunWith(PowerMockRunner.class),反之亦然。当你需要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,就需要加注解
@PrepareForTest。
2.2基本用法
详见 http://blog.csdn.net/knighttools/article/details/44630975
2.2.1和普通Mock的用法相同
PowerMockito.when(file.exists()).thenReturn(true);
2.2.2 Mock方法内部new出来的对象
File file = PowerMockito.mock(File.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.whenNew(File.class).withArguments("bbb").thenReturn(file);
PowerMockito.when(file.exists()).thenReturn(true);
2.2.3 Mock普通对象的final方法
ClassDependency depencency = PowerMockito.mock(ClassDependency.class);
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.when(depencency.isAlive()).thenReturn(true);
2.2.4.Mock普通类的静态方法
PowerMockito.mockStatic(ClassDependency.class);
PowerMockito.when(ClassDependency.isExist()).thenReturn(true);
2.2.5 Mock 私有方法
ClassUnderTest underTest = PowerMockito.mock(ClassUnderTest.class);
PowerMockito.when(underTest.callPrivateMethod()).thenCallRealMethod();
PowerMockito.when(underTest, "isExist").thenReturn(true);
2.2.6. Mock系统类的静态和final方法
ClassUnderTest underTest = new ClassUnderTest();
PowerMockito.mockStatic(System.class);
PowerMockito.when(System.getProperty("aaa")).thenReturn("bbb");
2.2.7 验证方法
(1) 验证静态方法:
PowerMockito.verifyStatic();
Static.firstStaticMethod(param);
(2) 扩展验证:
PowerMockito.verifyStatic(Mockito.times(2)); // 被调用2次
Static.thirdStaticMethod(Mockito.anyInt()); // 以任何整数值被调用
以上是关于使用mock模拟解决测试中依赖问题的主要内容,如果未能解决你的问题,请参考以下文章