目录

  • 1 Mockito
  • 2 各种模拟使用
    • 2.1 mock接口并验证
    • 2.2 mock具体类,并进行stub
    • 2.3 参数匹配器-Argument matchers
    • 2.4 验证实际调用的次数
    • 2.5 stub 空返回值方法
    • 2.6 按顺序验证行为
    • 2.7 冗余的mock对象验证
    • 2.8 迭代器风格的stub
    • 2.9 支持回调的stub
    • 2. 10 spy真实对象
    • 2-11 部分真实mock
    • 2-12 重置mock
    • 2-13 @Mock和@InjectMocks
    • 2-14 行为驱动开发模式BDD
  • 参考文献

1 Mockito

mockito是Java中用于单元测试的模拟框架,Mockito库支持模拟创建、验证和存根。

通常和Junit框架组合完成对项目的单元测试。

2 各种模拟使用

2.1 mock接口并验证

测试demo-1:

//1--mock一些接口, 使用verify验证某些行为是否发生仅过一次@Testvoid mockListTest() {List listMock = mock(List.class);listMock.add("one");listMock.get(1);listMock.clear();verify(listMock).add("one");verify(listMock).clear();verify(listMock).get(1);}

mock接口,并可verify行为是否发生过和已经发生次数。

2.2 mock具体类,并进行stub

测试demo-2:

//2--mock一些具体的类,并进行stub@Testvoid mockConcreteList() {LinkedList mockLinkedList = mock(LinkedList.class);when(mockLinkedList.get(0)).thenReturn("first");when(mockLinkedList.get(1)).thenThrow(new RuntimeException());System.out.println(mockLinkedList.get(0));
//        System.out.println(mockLinkedList.get(1));System.out.println(mockLinkedList.get(999));}

mock具体类,stub具体的行为返回值。

2.3 参数匹配器-Argument matchers

测试demo-3:

@Testvoid mockArgumentMatcherTest() {LinkedList mockLinkedList = mock(LinkedList.class);when(mockLinkedList.get(anyInt())).thenReturn("element");System.out.println(mockLinkedList.get(Integer.MAX_VALUE));//可以传入lambda表达式when(mockLinkedList.contains(argThat((str) -> {String strNew = (String) str;return strNew.length() > 5;}))).thenReturn(true);System.out.println(mockLinkedList.contains("cece"));System.out.println(mockLinkedList.contains("cecece"));verify(mockLinkedList).get(anyInt());}

运行结果:

可以使用内建的anyInt……系列或者自定义argThat,来完成stub需求,支持lambda表达式

2.4 验证实际调用的次数

测试demo-4:

@Testvoid verifyExactNumberTest() {LinkedList mockLinkedList = mock(LinkedList.class);mockLinkedList.add("one");mockLinkedList.add("two");mockLinkedList.add("two");mockLinkedList.add("three");mockLinkedList.add("three");mockLinkedList.add("three");//默认一次verify(mockLinkedList).add("one");verify(mockLinkedList, times(1)).add("one");//验证两次、三次verify(mockLinkedList, times(2)).add("two");verify(mockLinkedList, times(3)).add("three");//验证从未添加的元素verify(mockLinkedList, never()).add("never add");//验证atLeast、atMostverify(mockLinkedList, atLeast(1)).add("three");verify(mockLinkedList, atMost(1)).add("one");}

可以使用支持的times、never、atLeast和atMost进行调用次数验证。

2.5 stub 空返回值方法

测试demo-5:

@Testvoid stubVoidTest() {LinkedList mockLinkedList = mock(LinkedList.class);doThrow(new RuntimeException()).when(mockLinkedList).clear();//调用clear方法,返回异常mockLinkedList.clear();}

执行结果:

mock返回值为void方法。

2.6 按顺序验证行为

测试demo-6:

@Testvoid verifyInOrderTest() {List singleList = mock(List.class);singleList.add("was add first");singleList.add("was add second");//单一mock验证顺序InOrder singleInOrder = inOrder(singleList);singleInOrder.verify(singleList).add("was add first");singleInOrder.verify(singleList).add("was add second");List firstMock = mock(List.class);List secondMock = mock(List.class);firstMock.add("one");firstMock.add("two");secondMock.add("one");secondMock.add("two");InOrder order = inOrder(firstMock, secondMock);//多个mock验证添加顺序order.verify(firstMock).add("two");order.verify(secondMock).add("one");order.verify(secondMock).add("two");}

通过InOrder进行行为顺序验证,支持多个mock对象的顺序验证。

2.7 冗余的mock对象验证

测试demo-7:

@Testvoid redundantInvocationTest() {List mockList = mock(List.class);mockList.add("one");mockList.add("two");//这个没有验证mockList.add("three");verify(mockList).add("two");verify(mockList).add("one");verifyNoMoreInteractions(mockList);}

执行结果:

verifyNoMoreInteractions支持验证多余的交互行为(交互了但没有verify)。

2.8 迭代器风格的stub

测试demo-8:

@Testvoid stubIteratorTest() {List mockList = mock(List.class);when(mockList.get(1)).thenReturn("foo", "test");//按顺序返回System.out.println(mockList.get(1));System.out.println(mockList.get(1));//之后都是最后一个迭代test获胜System.out.println(mockList.get(1));}

执行结果:

可以返回多个值,每次调用都会向后迭代,超过长度会重复最后一个stub的结果。

2.9 支持回调的stub

测试demo-9:

@Testvoid stubWithCallbackTest() {List<String> mockList = mock(List.class);//使用thenAnswer传入回调when(mockList.get(anyInt())).thenAnswer(invocation -> {Object[] arguments = invocation.getArguments();Object mock = invocation.getMock();return "called with arguments: " + Arrays.toString(arguments);});System.out.println(mockList.get(111));}

运行结果:

支持通过thenAnswer传入lambda表达式,自定义回调函数处理返回结果。

2. 10 spy真实对象

测试demo-10:

@Testvoid spyRealObjectTest() {LinkedList<String> linkedList = new LinkedList<>();LinkedList<String> spy = spy(linkedList);spy.add("one");spy.add("two");System.out.println(spy.get(0));System.out.println(spy.get(1));//进行stubwhen(spy.size()).thenReturn(100);System.out.println(spy.size());verify(spy).add("one");List list = new LinkedList();List spy1 = spy(list);}

运行结果:

spy真实对象,将会调用对象的真实方法,同时可以支持stub对象行为,但是有局限性,比如下面情况:

//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)when(spy1.get(0)).thenReturn("foo");//You have to use doReturn() for stubbingdoReturn("foo").when(spy).get(0);

运行结果:

因为使用when,spy.get(0)将被调用,而此时还没有元素,会抛出异常。而doReturn没有调用方法,只是设置了返回值。

2-11 部分真实mock

测试demo-11:

@Testvoid realPartMockTest() {CalculatorMapper mock = mock(CalculatorMapper.class);//调用selectFirst调用真实方法when(mock.selectFirst(anyInt())).thenCallRealMethod();Assertions.assertEquals(101, mock.selectFirst(1));}

thenCallRealMethod支持调用真实对象方法。

2-12 重置mock

测试demo-12:

@Testvoid resetMockTest() {List mock = mock(List.class);when(mock.size()).thenReturn(10);mock.add(1);//reset所有发生的调用和行为reset(mock);verifyNoMoreInteractions(mock);}

一般我们测试都是针对单独的一个功能,没有必要进行重置。

2-13 @Mock和@InjectMocks

测试demo-13:

@ExtendWith(MockitoExtension.class)
public class CalculatorManagerTest {//注入mock,会对注入的属性根据测试类中定义的mock类进行注入。@InjectMocksprivate CalculatorService calculatorService;//mock其它类,需要对方法返回值进行mock设置@Mock private CalculatorMapper calculatorMapper;@BeforeEachvoid setUp() {}@Testpublic void calculatorManagerTest() {when(calculatorMapper.selectFirst(anyInt())).thenReturn(100);when(calculatorMapper.selectSecond(anyInt())).thenReturn(100);Assertions.assertEquals(200, calculatorService.add(1, 1));}
}

可以使用注解@Mock更简单的mock一个对象,如果对象中有注入对象,可以使用@InjectMocks进行mock对象注入。

2-14 行为驱动开发模式BDD

BDD一般定义为下:

  • 给定given:场景开头的初始上下文,一个或多个子句.
  • 时间when:触发场景的事件.
  • 然后then:在一个或多个条款中的预期结果。

测试demo-14:

@Testvoid bddMockTest() {List mockList = mock(List.class);//given,列表获取常见given(mockList.get(anyInt())).willReturn(100, 200, 300);//when,第一次获取mockList.get(0);//then,判断获取第二次结果Assertions.assertEquals(mockList.get(0), 200);//verify行为的bdd模式then(mockList).should(times(2)).get(0);}

mockito工作组建议使用的编写测试模式。

库中已经封装了对于的BDD调用方式。

参考文献

[1] Mockito文档.

Java测试-mockito学习相关推荐

  1. TurtleSoup Java测试学习项目

    TurtleSoup Java测试学习项目 项目文件下载: Java测试学习项目 前言 实习题目给的是全英文的,由于整个描述也比较长,前言这里做一个简述概括,整个实习2主要是教我们如何通过测试用例进行 ...

  2. 2021年,Java开发者值得学习的13项技能

    本文分享自百度开发者中心2021年,Java开发者值得学习的13项技能 作者 | Olivia Cuthbert 译者 | 王强 策划 | 刘燕 如果你想在这个竞争激烈的世界里,成为一名熟练开发 Ja ...

  3. 2021 年,Java 开发者值得学习的 13 项技能

    作者 | Olivia Cuthbert 译者 | 王强 策划 | 刘燕 如果你想在这个竞争激烈的世界里,成为一名熟练开发 Java 项目的开发人员,你应该学习很多东西才行.你需要掌握许多技能,具体应 ...

  4. java测试步骤_java测试框架的方法

    项目开发过程中使用的单元测试框架有Junit.TestNG以及Mockito,Junit和TestNG使用的比较多,Mockito最近才开始使用. TestNG与JUnit的相同点 1. 使用anno ...

  5. java测试有哪些_java测试有哪些欢迎来电

    java测试有哪些欢迎来电,5.学员毕业后,仍可随时回来,免费技术提升,一次交费,永久学习. java测试有哪些欢迎来电, 单元测试的不神器,提高运行速度,跟真实环境解耦.jacoco:java 的代 ...

  6. Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论

    Java虚拟机JVM学习06 自定义类加载器 父委托机制和命名空间的再讨论 创建用户自定义的类加载器 要创建用户自定义的类加载器,只需要扩展java.lang.ClassLoader类,然后覆盖它的f ...

  7. [转]java.lang.instrument 学习(一)

    [转]java.lang.instrument 学习(一)  收藏 sunyh 发表于 10个月前 阅读 40 收藏 3 点赞 1 评论 0 转自:http://jiangbo.me/blog/201 ...

  8. Java IO流学习总结七:Commons IO 2.5-FileUtils

    Java IO流学习总结七:Commons IO 2.5-FileUtils 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/5497 ...

  9. Java IO流学习总结六:ByteArrayInputStream、ByteArrayOutputStream

    Java IO流学习总结六:ByteArrayInputStream.ByteArrayOutputStream 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/ar ...

最新文章

  1. 25 iOS performance TipsTricks 笔记
  2. 一个4体低位交叉的存储器_GD25Q16CSIG|NRAM存储器的原理及优势是什么?
  3. [刷题]算法竞赛入门经典(第2版) 4-3/UVa220 - Othello
  4. Hadoop从安装Linux到搭建集群环境
  5. 关于Java中 求Logn/log2 的精度问题。
  6. Hibernate开发和对象状态
  7. eclipse web项目中css无法显示
  8. 游戏大魔王少不了王者荣耀壁纸图片
  9. Rust : wasm尝试 与wasmtime库
  10. esxi 环境 西数硬盘测试软件,总算基本完美的折腾好ESXI+群晖+NVME
  11. 千方百剂医药管理系统对接第三方WMS系统(天力士物流)
  12. python调用百度地图,通过经纬度定位
  13. idea maven添加子moudle父pom被覆盖
  14. 云原生数据湖以存储、计算、数据管理等能力通过信通院评测认证
  15. 淘宝近12亿条用户信息泄露,犯罪分子获利34万
  16. SpringBoot+MongoDB GridFS文件上传、下载、预览实战
  17. 【Python网络编程和并发-多线程共享数据混乱引出同步锁】
  18. 高速电路设计基本概念之——近端串扰和远端串扰
  19. JS生成 GUID 或 UUID 四种方法
  20. Android仿英雄联盟/斗鱼波形加载动画

热门文章

  1. a标签与link标签的区别
  2. php公众号交友源码_个性定制微信导航源码,PHP公众号导航源码,含手机wap版,微信数据...
  3. 中国铜带行业市场供需与战略研究报告
  4. 沁恒全方位提供多种USB串口驱动第3代USB转串口产品
  5. 字号磅、像素、厘米转换
  6. 阿里云服务器系统(linux)配置nginx
  7. 在Mysql数据库里通过存储过程实现树形的遍历
  8. php 计算函数 (加,比较用法,除,减,求余,乘)
  9. 人人都爱写总结,却少有人做计划
  10. UESTC 1546 Bracket Sequence