草庐IT

Mockito超全用例文档

Gwen小苏 2023-04-10 原文

文章目录

一.mockito要注意的点

1. mock的对象直接调用其方法会返回null

2.执行真实的被测试方法

①thenCallRealMethod + 实现类:

解析:

mock接口不能和callRealMethod一起用,因为接口没有实现!(即使用spy重新封装也不行!)会报错哦~

但是,如果callRealMethod的方法里面用到了其他外部接口的方法,并且最后结果依赖于这些接口的返回值,则最后执行真实方法得到的接口会偏离真实结果,除非你其他方法也一起callRealMethod。

@Mock
private static LogisticsExpenseCostServiceImpl logisticsExpenseCostService;// 正确:mock被测试类实现类
//@Mock
//private static LogisticsExpenseCostServiceImpl logisticsExpenseCostService;// 错误:mock接口且想callRealMethod,

@org.junit.Test
public void test() throws ParseException {
    ... ...
when(logisticsExpenseCostService.findExpenseAndDetail(null, dataReadingEntity)).thenCallRealMethod();
List<ExpenseCostQueryItem> expenseAndDetail = logisticsExpenseCostService.findExpenseAndDetail(null, dataReadingEntity);
    ... ...
} 

②injectMock

解析:

@Mock: 创建一个Mock.

@InjectMocks: 创建一个实例,简单的说是这个Mock可以调用真实代码的方法,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中。如果只实例化对象不加injectmock会,则被测试接口用到的其他依赖对象为空,无法注入报空指针。

但是,在doReturn().when(A)中,injectMcok的对象不能放入A的位置,因为A的位置只能是mock/spy对象,不过可以放在when(B).thenReturn()的B的位置,所以injectMock可以再用spy代理一起使用就可以用doReturn了

// 与mock不同,它需要new LogisticsExpenseCostServiceImpl()实例化
@InjectMocks
private static LogisticsExpenseCostService logisticsExpenseCostService = new LogisticsExpenseCostServiceImpl();
@org.junit.Test
public void test() throws ParseException {
    ...
    LogisticsExpenseCostService spy = spy(logisticsExpenseCostService);// spy代理
    doReturn(mockExpenseCostQueryItems).when(spy).constructExpenseCostList(null,dataReadingEntity);// 这里when(spy),不能when(logisticsExpenseCostService)~
    doReturn(mockExpenseCostDetailMap).when(spy).constructExpenseCostDetailMap(null,dataReadingEntity);
    List<ExpenseCostQueryItem> expenseAndDetail = spy.findExpenseAndDetail(null, dataReadingEntity);
    System.out.println(JSON.serialize(expenseAndDetail));
    ...
} 

3.verify测试是否被调用

4.激活mock功能的几种方式

二.mock对象的方式

1.spy

spy可以模拟部分实际代码,部分mock代码

被spy后,调用被打桩的方法会返回thenReturn/doReturn的值,调用没被打桩方法则是真实调用返回的值

使用方式:spy(XXX)或者@Spy注解

注意:被spy的对象需要已实例化(= new XXX, @Autowire…)

2.深度mock

优化需要把调用链所有涉及对象都mock的麻烦

使用方式:@Mock(answer=Answre.RETURNS_DEEP_STUBS)

如果不加此注解,那lession03Service.get()得到的对象也是需要mock才能用,否则空指针

三.stup打桩

1.doReturn.when:不会走函数方法

为了屏蔽复杂的第三方接口需要mock大量对象,使用doReturn直接屏蔽,注意参数匹配器,要是传参不匹配还是会走的

2.when.thenReturn:调用真实的方法

如果你不想调用真实的方法而是想要mock的话,就不要使用这个方法。

3.其他

thenReturn:模拟调用后返回值.

thenReturn多个参数:代表第x次返回参数位置x的值

thenThrow:模拟调用后抛异常

doNothing.when:模拟调用后不做任何事情

doThrow:模拟调用后抛异常



thenAnswer:动态模拟返回参数值的十倍

四、Mockito argument Matchers 参数匹配器

1.anyXX

anyXXX的方法使用,可以减少很多打桩条件

2.isA和any

isA代表传入参数只要是A或A的实现子类都符合这个条件,可以返回桩

any只要符合function声明的参数,都可以通过


五.常见错误

1.使用any常见错误,部分传入真实对象,部分传入any

那怎么办呢?使用eq实现具体值传参

2.verify的时候,调用的和校验的传参看似一样,其实不同对象导致校验报错

可以把对象抽出来,再放参数

3.打桩顺序问题,-1放最后时,会覆盖前面两个打桩,因为anyString包括了eq(xxx)

如果这样写,后面两行只会覆盖部分的anyString,当为alex返回100,wang返回200,其他返回-1

4.anyXX是不包括null的

比如有个参数类型是List,这时你when.thenReturn时传入anyList,而你最后调用时传入null,这时候是不符合when的打桩的

如果想包含null,可以使用any()

5.mock复杂的数据实体时,如果是多层数据结构,最里层的数据结构需要手动转类型

Map<String, List<ExpenseCostDetailQueryItem>> mockExpenseCostDetailMap = SnakeCaseJsonUtils.readObject("classpath:testData/expenseCostDetailMapJsonData",Map.class);
// 比如这里mock的数据返回是Map里面有个List,List里面是Model,当我们没有手动转类型,我们会得到JSONObeject的对象

// 手动转类型
for (Map.Entry<String, List<ExpenseCostDetailQueryItem>> stringListEntry : mockExpenseCostDetailMap.entrySet()) {
    List<ExpenseCostDetailQueryItem> value = stringListEntry.getValue();
    stringListEntry.setValue(JSONObject.parseArray(JSON.serialize(value),ExpenseCostDetailQueryItem.class));
}

6.doReturn肯定会跳过mock的方法,如果没有那就是你参数不匹配~

这里的参数是any任意值和dataReadingEntity实体,当你实际调用的dataReadingEntity和匹配器里的不同,那就不会跳过~

doReturn(mockExpenseCostQueryItems).when(spy).constructExpenseCostList(any(),eq(dataReadingEntity));

六.好的mockito习惯

1.善用@after

对不同方法里对同一个全局对象进行打桩,会互相影响,这时候加@after去reset可以避免影响

2.优雅的断言–陈述性断言

3.断言提示

4.手动实现断言条件

https://www.bilibili.com/video/BV1jJ411A7Sv?p=10

有关Mockito超全用例文档的更多相关文章

  1. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

  2. Ruby 等同于 Sphinx 文档生成器? - 2

    Ruby有一些不错的文档生成器,例如Yard、rDoc,甚至Glyph。问题是Sphinx可以做网站、PDF、epub、LaTex等。它在重组文本中完成所有这些事情。在Ruby世界中有替​​代方案吗?也许是程序的组合?如果我也能使用Markdown就更好了。 最佳答案 自1.0版以来,Sphinx有了“域”的概念,它是从Python和/或C以外的语言标记代码实体(如方法调用、对象、函数等)的方法。有一个rubydomain,所以你可以只使用Sphinx本身。您唯一会缺少的(我认为)是Sphinx使用autodoc从源代码自动创建文档

  3. ruby-on-rails - 在 irb 中阅读文档 - 2

    我怀念ipython的一件事是它有一个?为特定功能挖掘文档的运算符。我知道ruby​​有一个类似的命令行工具,但是我在irb中调用它非常不方便。ruby/irb有类似的东西吗? 最佳答案 Pry是IPython的Ruby版本,它支持?命令来查找有关方法的文档,但语法略有不同:pry(main)>?File.dirnameFrom:file.cinRubyCore(CMethod):Numberoflines:6visibility:publicsignature:dirname()Returnsallcomponentsofthef

  4. ruby - 使用 Nokogiri 和 Ruby 从 html 文档获取链接和 href 文本? - 2

    我正在尝试使用nokogirigem提取页面上的所有url及其链接文本,并将链接文本和url存储在散列中。FooBar我想回去{"Foo"=>"#foo","Bar"=>"#bar"} 最佳答案 这是一个单行:Hash[doc.xpath('//a[@href]').map{|link|[link.text.strip,link["href"]]}]#=>{"Foo"=>"#foo","Bar"=>"#bar"}拆分一点可以说更具可读性:h={}doc.xpath('//a[@href]').eachdo|link|h[link.t

  5. ruby - 如何让 Nokogiri 解析并返回 XML 文档? - 2

    这是一些奇怪的例子:#!/usr/bin/rubyrequire'rubygems'require'open-uri'require'nokogiri'print"withoutread:",Nokogiri(open('http://weblog.rubyonrails.org/')).class,"\n"print"withread:",Nokogiri(open('http://weblog.rubyonrails.org/').read).class,"\n"运行此返回:withoutread:Nokogiri::XML::Documentwithread:Nokogiri::

  6. H2数据库配置及相关使用方式一站式介绍(极为详细并整理官方文档) - 2

    目录H2数据库入门以及实际开发时的使用1.H2数据库的初识1.1H2数据库介绍1.2为什么要使用嵌入式数据库?1.3嵌入式数据库对比1.3.1性能对比1.4技术选型思考2.H2数据库实战2.1H2数据库下载搭建以及部署2.1.1H2数据库的下载2.1.2数据库启动2.1.2.1windows系统可以在bin目录下执行h2.bat2.1.2.2同理可以通过cmd直接使用命令进行启动:2.1.2.3启动后控制台页面:2.1.3spring整合H2数据库2.1.3.1引入依赖文件2.1.4数据库通过file模式实际保存数据的位置2.2H2数据库操作2.2.1Mysql兼容模式2.2.2Mysql模式

  7. Ruby YAML 多文档 - 2

    这是我的YAML文件“test.yml”:---alpha:100.0beta:200.0gama:300.0---3...第一个文档是一个散列。第二个文档是一个整数。我正在尝试将它们作为散列和整数加载到Ruby程序中。这是我目前的尝试:require'yaml'variables=YAML.load_file('test.yml')putsvariables.inspect 最佳答案 要访问单个文件中的多个YAML文档,请使用load_stream方法(正如“matt”在对其他答案之一的评论中提到的):YAML.load_stre

  8. ruby - 自动将院子文档框架添加到现有的 Rails 遗留代码中 - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭4年前。Improvethisquestion我希望能够将模板化的YARD文档样式注释插入到我现有的Rails遗留应用程序中。目前它的评论很少。我想要具有指定参数的类header和方法header(通过从我假定的方法签名中提取)和返回值的占位符。在PHP代码中,我有一些工具可以检查代码并在适当的位置创建插入到代码中的文档header注释。在带有Ducktyping等的Ruby中,我确信诸如@params等类型之类

  9. ruby - 以编程方式将数据插入 InDesign 文档 - 2

    我必须使用Adob​​eInDesign来创建文档。我们基本上需要在整个文档中有几个变量(公司名称、项目名称等)需要填写。我想知道是否有一种方法可以采用现有模板,并使用我熟悉的语言(Ruby、Python等)以编程方式填充这些模板。我尝试使用文本编辑器打开Adob​​eInDesign文件-但是当我使用Notepad++进行修改然后在InDesign中打开文件时,它告诉我文件已损坏。如果您对以编程方式构建InDesign文档有任何见解或了解任何教程,我们将不胜感激。附言我尝试查看Adob​​e的ExtendScript,但没有找到太多适用于InDesign的文档。感谢您的帮助!

  10. Ruby 并发/异步处理(简单用例) - 2

    我一直在研究ruby​​的并行/异步处理能力,并阅读了许多文章和博客文章。我查看了EventMachine、Fibers、Revactor、Reia等。不幸的是,我无法为这个非常简单的用例找到简单、有效(且非IO阻塞)的解决方案:File.open('somelogfile.txt')do|file|whileline=file.gets#(R)ReadfromIOline=process_line(line)#(P)Processthelinewrite_to_db(line)#(W)WritetheoutputtosomeIO(DBorfile)endend你看到了吗,我的小脚本正

随机推荐