MockiTo 测试用mock框架
引入
编写UT测试用例时,使用mock可以只针对待测方法进行验证,而无需考虑真实数据和调用方法的影响。
依赖
<dependency> <groupId>org.mockitogroupId> <artifactId>mockito-allartifactId> <version>1.10.19version> <scope>testscope> dependency>
使用
参考文章:https://www.cnblogs.com/yinyunmoyi/p/14203794.html
初始化
测试类中进行UT编写之前需要初始化MockiTo,自动创建mock对象
@BeforeClass public void initMocks() throws Exception{ System.out.println("Before Class"); //MockitoAnnotations.initMocks(this),其中this就是单元测试所在的类,在initMocks函数中Mockito会根据类中不同的注解(如@Mock, @Spy等)创建不同的mock对象,即初始化工作 MockitoAnnotations.initMocks(this); }
@Before, @BeforeClass, @BeforeEach 和 @BeforeAll 之间的不同
特性 |
Junit 4 | Junit 5 |
|
@BeforeClass | @BeforeAll |
|
@AfterClass | @AfterAll |
|
@Before | @BeforeEach |
|
@After |
@AfterEach |
标记的代码@Before
在每次测试之前执行,而@BeforeClass
在整个测试夹具之前运行一次。如果你的测试类有十个测试,则@Before
代码将执行十次,但@BeforeClass
仅执行一次。
通常,
@BeforeClass
当多个测试需要共享相同的计算昂贵的设置代码时,可以使用。建立数据库连接属于此类。你可以将代码从@BeforeClass
移到@Before
,但是测试运行可能需要更长的时间。注意,标记的代码@BeforeClass
作为静态初始化程序运行,因此它将在创建测试夹具的类实例之前运行。-https://www.cnblogs.com/yaoyaoo/p/14344684.html
创建mock
一般使用注解方式
@InjectMocks
用它标注的类会自动装配其中已经被在当前测试类中用 @Mock 和 @Spy 标注的字段(按名称匹配),该类.method(param...)是真实方法调用 =》该注解标记在待测类上
@InjectMocks ModelDaoImpl modelDao; @Mock Mediator mediator; ...{ // 这里调用的create是真实的方法,这里面如果有mediator调用某个方法,就可以通过自动装配事先设置它的行为了 Mockito.when(mediator.get(0)).thenReturn("foo"); modelDao.create(); ... }
设置一类行为
有返回值
方式一:会进入方法内,只是返回值是设定的返回值
Mockito.when(A.method(param...)).thenReturn(B);
方式二:并不会进入方法内,触发该方法就直接返回设定的值
Mockito.doReturn(C).when(A).method(B);
无返回值
返回值类型为 void的方法才能使用
doNothing().when(A.method(param...));
部分模拟
对于局部变量,有时候是不好准确模拟的,即使创建一个相同的对象
如这种情况
methodA() { Request request = new Request(); // 设置request的属性 ... // 调用方法 Response response = serviceInvoker.invoke(SERVICE_NAME, request); }
即便模拟invoke
// 创建request对象并设置其属性 Mockito.when(serviceInvoker.invoke(SERVICE_NAME, request)).thenReturn("foo");
也是行不通的,因为在待测试的代码中,request 是一个局部变量,它的地址和我们创建出来的对象地址是不同的,也就无法准确的进行模拟
解决方式可以是将生成Request的代码抽出来为一个方法,将该方法局部模拟,使用spy,spy部分模拟的对象,除了设定的方法,其他的都会按照原有真实方法执行
spy:
一,注解 @spy
二,手动
// 使用部分模拟需要用spy方法,它必须是某个已经建立好的对象的封装,不能用class对象为构造参数 List list = new LinkedList(); List mockedList = Mockito.spy(list);
将生成Request的代码抽出来为一个方法
Request request = getRequest(); // 调用方法 Response response = serviceInvoker.invoke(SERVICE_NAME, request);
来mock,instance是spy出来的
// 模拟getRequest方法的行为 Mockito.when(instance.getRequest()).thenReturn(request); // 完成我们一开始想要的行为定义 Mockito.when(serviceInvoker.invoke(SERVICE_NAME, request)).thenReturn("foo");
mock静态和私有方法
实测网上的方式搞不了