Mockito是一种Java Mock框架,主要就是用来做Mock测试的,它可以模拟任何Spring管理的Bean、模拟方法的返回值、模拟抛出异常等等,同时也会记录调用这些模拟方法的参数、调用顺序,从而可以校验出这个Mock对象是否有被正确的顺序调用,以及按照期望的参数被调用。
Mockito的特别之处在于它是一个强大的用于Java开发的模拟测试框架,通过Mockito我们可以创建和配置Mock对象,进而简化有外部依赖的类的测试。Mockito提供了大量的静态方法,用于帮助我们来mock对象,验证行为等等
本人的理解:就是在实际调用代码前,我就规定它返回什么。
一个例子:
// 您可以模拟具体的类,而不仅仅是接口s
LinkedList mockedList = mock(LinkedList.class);
// 或者使用Mockito 4.10.0+更简单
// LinkedList mockedList = mock();
// 存根(stubbing)在实际执行之前出现
when(mockedList.get(0)).thenReturn("first");
// 以下打印“first”
System.out.println(mockedList.get(0));
// 下面打印“null”,因为get(999)没有存根
System.out.println(mockedList.get(999));
在测试对象发生特定事件时抛出异常。
例1:
PowerMockito
.doThrow(new NotPermittedException(HttpServletResponse.SC_FORBIDDEN,
ErrorMsgResourceKeys.auth_accessDenied, "GroupPermissions", null))
.when(AdminPermissionCheck.class);
AdminPermissionCheck.checkAdminPermission(authorizationsVO, lstPermissions, true);
例2:
@Test
void whenConfigVoidRetunMethodToThrowEx_thenExIsThrown() {
MyDictionary dictMock = mock(MyDictionary.class);
doThrow(IllegalStateException.class).when(dictMock)
.add(anyString(), anyString());
assertThrows(IllegalStateException.class, () -> {
dictMock.add("word", "meaning");
});
}
最初接触 Mockito 还思考并尝试过如何用它来 mock 返回值为 void 的方法,然而 Google 查找到的一般都会说用 doThrow()
的办法
doThrow(new RuntimeException()).when(mockObject).methodWithVoidReturn();
因为无法使用常规的 when(mockObject.foo()).thenReturn(...)
的方法。
当时我就纳闷,为何我想 mock 一个返回值为 void 的方法,却是在模拟抛出一个异常,现在想来如果一个返回值为 void 的方法,为何要去 mock 这个方法呢?
回想一个我们要 mock 一个方法的意图是什么:
对于 void 返回值的方法,如果要验证有没有被调用过几次可以在事后用 verify()
方法去断言。所以基本上对于 void 返回值的方法一般可不用去 mock 它,只需用 verify() 去验证,或者就是像前面一样模拟出现异常时的情况。
解决单元测试Mockito模拟方法内new对象的问题_mockito new_半斤米粉闯天下的博客-CSDN博客
记PowerMockito whenNew的一个坑_Brain_L的博客-CSDN博客
@PrepareForTest后面应该加上被测试的类,而不是要whenNew的类,被这个坑过两次了,特此记录下。
java - doReturn().when()与when().thenReturn() - 成长之路 - SegmentFault 思否
doReturn().when()是无副作用的。
when().thenReturn()是有副作用的。
如果有时候报错missing thenReturn等问题,可以把(对象.方法)
改为.(对象).方法
如果使用Mockito.mock(Gson.class)
,会报错:
Mockito cannot mock/spy because : - final class
这是因为低版本的mockito是不能mock final类的。
解决方案:Mockito不能mock final类的解决办法_南瓜慢说的博客-CSDN博客
改变mockito的版本,修改maven依赖如下:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.3.3</version>
</dependency>
重跑测试,问题解决!
然而,万一随意变动依赖导致其他test失效就得不偿失了,因此最好从业务逻辑上对代码进行改造,这里我们涉及的代码为:
Gson gson = new Gson();
String file = (String) gson.fromJson(result, Map.class).get("data");
Gson是final修饰的类,我们要调用它的fromJson方法,其实我们可以构造一个json格式的字符串result:
{data:logs}
然后fromJson就能正常调用了。