存根类 测试代码 java_嘲弄和存根–了解Mockito的测试双打

存根类 测试代码 java

介绍

我遇到的一件事是使用模拟框架的团队假设他们在模拟。
他们并不知道Mocks只是Gerard Meszaros在xunitpatterns.com上分类的“测试双打”之一。

重要的是要认识到每种类型的双重测试在测试中扮演着不同的角色。 用与学习不同模式或重构相同的方式,您需要了解每种类型的测试double的原始角色。 然后可以将它们组合起来以满足您的测试需求。
我将简要介绍这种分类的产生方式以及每种类型的不同之处。
我将在Mockito中使用一些简短的简单示例进行此操作。

一段简短的历史

多年来,人们一直在编写系统组件的轻量级版本以帮助进行测试。 通常,这被称为存根。 在2000年的文章“ Endo-Testing:使用模拟对象进行单元测试”中介绍了模拟对象的概念。 从那时起,Meszaros将Stub,Mocks和许多其他类型的测试对象归类为Double Double。
该术语已由Martin Fowler在“ Mocks Are n't Stubs”中引用,并在Microsoft社区中被采用,如“ Exploring The Test Doubles Continuum of Test Doubles”中所示。
参考部分中显示了这些重要论文的链接。

考试双打的类别

上图显示了常用的双重测试类型。 以下URL提供了对每个模式及其功能以及替代术语的很好的交叉引用。
http://xunitpatterns.com/Test%20Double.html

莫基托

Mockito是一个测试间谍框架,学习起来非常简单。 Mockito值得注意的是,在测试之前没有定义任何模拟对象的期望,因为它们有时在其他模拟框架中也是如此。 开始嘲笑时,这会导致更自然的样式(IMHO)。
以下示例在这里纯粹是为了简单演示如何使用Mockito实施不同类型的测试双打。

网站上有大量有关如何使用Mockito的特定示例。
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html

使用Mockito测试双打

以下是一些使用Mockito的基本示例,以显示Meszaros定义的每个测试双打的作用。
我为每个对象都提供了指向主要定义的链接,因此您可以获得更多示例和完整定义。

虚拟对象

http://xunitpatterns.com/Dummy%20Object.html
这是所有测试双打中最简单的一次。 这是一个没有实现的对象,仅用于填充与测试无关的方法调用的参数。

例如,下面的代码使用大量代码来创建客户,这对测试并不重要。
只要客户数恢复为1,该测试就不会在乎添加哪个客户。

public Customer createDummyCustomer() {County county = new County('Essex');City city = new City('Romford', county);Address address = new Address('1234 Bank Street', city);Customer customer = new Customer('john', 'dobie', address);return customer;
}@Test
public void addCustomerTest() {Customer dummy = createDummyCustomer();AddressBook addressBook = new AddressBook();addressBook.addCustomer(dummy);assertEquals(1, addressBook.getNumberOfCustomers());
}

我们实际上并不关心客户对象的内容,但是它是必需的。 我们可以尝试使用null值,但是如果代码正确,则可能会引发某种异常。

@Test(expected=Exception.class)
public void addNullCustomerTest() {Customer dummy = null;AddressBook addressBook = new AddressBook();addressBook.addCustomer(dummy);
}

为了避免这种情况,我们可以使用一个简单的Mockito假人来获得所需的行为。

@Test
public void addCustomerWithDummyTest() {Customer dummy = mock(Customer.class);AddressBook addressBook = new AddressBook();addressBook.addCustomer(dummy);Assert.assertEquals(1, addressBook.getNumberOfCustomers());
}

正是这个简单的代码创建了一个要传递给调用的虚拟对象。

Customer dummy = mock(Customer.class);

不要被模拟语法所迷惑-这里扮演的角色是虚拟的,而不是模拟的。
区别在于测试双重性的作用,而不是用于创建双重性的语法。

该类可以轻松替代客户类,并使测试非常容易阅读。

测试存根

http://xunitpatterns.com/Test%20Stub.html
测试存根的作用是将受控值返回到要测试的对象。 这些被描述为测试的间接输入。 希望有一个例子可以阐明这意味着什么。

采取以下代码

public class SimplePricingService implements PricingService
{ PricingRepository repository;public SimplePricingService(PricingRepository pricingRepository) {this.repository = pricingRepository;}@Overridepublic Price priceTrade(Trade trade) {return repository.getPriceForTrade(trade);}@Overridepublic Price getTotalPriceForTrades(Collectiontrades) {Price totalPrice = new Price();for (Trade trade : trades){Price tradePrice = repository.getPriceForTrade(trade);totalPrice = totalPrice.add(tradePrice);}return totalPrice;}

SimplePricingService具有一个协作对象,即交易存储库。 交易存储库通过getPriceForTrade方法将交易价格提供给定价服务。
为了测试SimplePricingService中的业务逻辑,我们需要控制这些间接输入
即我们从未通过测试的输入。 如下所示。

在下面的示例中,我们对PricingRepository存根以返回可用于测试SimpleTradeService的业务逻辑的已知值。

@Test
public void testGetHighestPricedTrade() throws Exception {Price price1 = new Price(10); Price price2 = new Price(15);Price price3 = new Price(25);PricingRepository pricingRepository = mock(PricingRepository.class);when(pricingRepository.getPriceForTrade(any(Trade.class))).thenReturn(price1, price2, price3);PricingService service = new SimplePricingService(pricingRepository);Price highestPrice = service.getHighestPricedTrade(getTrades());assertEquals(price3.getAmount(), highestPrice.getAmount());
}

破坏者的例子

测试存根有2个常见的变体:响应者和破坏者。
如前面的示例,使用响应者来测试快乐路径。
破坏者用于测试以下异常行为。

@Test(expected=TradeNotFoundException.class)
public void testInvalidTrade() throws Exception {Trade trade = new FixtureHelper().getTrade();TradeRepository tradeRepository = mock(TradeRepository.class);when(tradeRepository.getTradeById(anyLong())).thenThrow(new TradeNotFoundException());TradingService tradingService = new SimpleTradingService(tradeRepository);tradingService.getTradeById(trade.getId());
}

模拟对象

http://xunitpatterns.com/Mock%20Object.html
模拟对象用于在测试期间验证对象行为。 通过对象行为,我的意思是我们检查在运行测试时是否在对象上执行了正确的方法和路径。
这与存根的支持作用完全不同,存根用于为您正在测试的任何结果提供结果。 在存根中,我们使用为方法定义返回值的模式。

when(customer.getSurname()).thenReturn(surname);

在模拟中,我们使用以下形式检查对象的行为。

verify(listMock).add(s);

这是一个简单的示例,我们要测试是否正确审核了新交易。
这是主要代码。

public class SimpleTradingService implements TradingService{TradeRepository tradeRepository;AuditService auditService;public SimpleTradingService(TradeRepository tradeRepository, AuditService auditService){this.tradeRepository = tradeRepository;this.auditService = auditService;}public Long createTrade(Trade trade) throws CreateTradeException {Long id = tradeRepository.createTrade(trade);auditService.logNewTrade(trade);return id;
}

下面的测试为贸易存储库创建存根,并为AuditService创建模拟
然后,我们在模拟的AuditService上调用verify,以确保TradeService调用了
logNewTrade方法正确

@Mock
TradeRepository tradeRepository;@Mock
AuditService auditService;@Test
public void testAuditLogEntryMadeForNewTrade() throws Exception { Trade trade = new Trade('Ref 1', 'Description 1');when(tradeRepository.createTrade(trade)).thenReturn(anyLong()); TradingService tradingService = new SimpleTradingService(tradeRepository, auditService);tradingService.createTrade(trade);verify(auditService).logNewTrade(trade);
}

以下行对模拟的AuditService进行检查。

verify(auditService).logNewTrade(trade);

该测试使我们能够证明审计服务在创建交易时的行为正确。

测试间谍

http://xunitpatterns.com/Test%20Spy.html
值得一看上面的链接,以严格定义测试间谍。
但是在Mockito中,我喜欢使用它来包装实际对象,然后验证或修改它的行为以支持您的测试。 这是我们检查列表的标准行为的示例。 注意,我们既可以验证是否调用了add方法,也可以断言该项目已添加到列表中。

@Spy
List listSpy = new ArrayList();@Test
public void testSpyReturnsRealValues() throws Exception {String s = 'dobie';listSpy.add(new String(s));verify(listSpy).add(s);assertEquals(1, listSpy.size());
}

将其与仅可验证方法调用的模拟对象进行比较。 因为我们仅模拟列表的行为,所以它不记录已添加项目,并且在调用size()方法时返回默认值零。

@Mock
ListlistMock = new ArrayList();@Test
public void testMockReturnsZero() throws Exception {String s = 'dobie';listMock.add(new String(s));verify(listMock).add(s);assertEquals(0, listMock.size());
}

testSpy的另一个有用功能是能够对返回调用进行存根。 完成此操作后,该对象将表现正常,直到调用存根方法为止。
在此示例中,我们将get方法存根以始终引发RuntimeException。 其余行为保持不变。

@Test(expected=RuntimeException.class)
public void testSpyReturnsStubbedValues() throws Exception {listSpy.add(new String('dobie'));  assertEquals(1, listSpy.size());when(listSpy.get(anyInt())).thenThrow(new RuntimeException());listSpy.get(0);
}

在此示例中,我们再次保留了核心行为,但更改了size()方法以初始返回1,并为所有后续调用返回5。

public void testSpyReturnsStubbedValues2() throws Exception {int size = 5;when(listSpy.size()).thenReturn(1, size);int mockedListSize = listSpy.size();assertEquals(1, mockedListSize);mockedListSize = listSpy.size();assertEquals(5, mockedListSize);  mockedListSize = listSpy.size();assertEquals(5, mockedListSize);  
}

这真是不可思议!

假物件

http://xunitpatterns.com/Fake%20Object.html
假物品通常是手工制作或重量较轻的物品,仅用于测试,不适合生产。 一个很好的例子是内存数据库或伪造的服务层。

它们往往提供比标准测试双打更多的功能,因此通常不适合使用Mockito进行实现。 这并不是说它们不能像这样构造,只是可能不值得采用这种方式来实现。

参考:“ 小事半解 ” – 敏捷工程技术博客上来自JCG合作伙伴 John Dobie的Mockito了解测试双打 。


翻译自: https://www.javacodegeeks.com/2012/05/mocks-and-stubs-understanding-test.html

存根类 测试代码 java

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/355775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

只会python怎么挣钱_业余学python有用吗

Python的火热我就不细说了,大家都是编程老司机,对最前沿最火热的编程语言肯定比我还了解。前几天,我看了一篇“如何用Python制造一个抖音小姐姐发掘器?”,阅读量竟然比头条上的还多了一倍。可见Python的火热&#xff0…

物联网项目:将Arduino连接到Ubidots和Android –第1部分

这个物联网项目探索了物联网的一个重要方面:如何使用以太网屏蔽将Arduino连接到物联网云平台 。 这方面很重要,因为可以将数据存储在云中然后进行分析。 一旦数据(如传感器值)存储在云中,便可以使用智能手机访问数据并…

iphone黑屏转圈_iphone XR被曝新BUG,众多用户中招,无规律黑屏假死

进入今年一月份以来,苹果放宽了对iphone的定价,所以各大电商都对多款iphone XR进行了上千元的降价。这也让iphone XR瞬间取代了华为MATE 20 PRO成为新的“真香机”。而随着iphone XR的用户越来越多,这款手机也再次爆出新的BUG。根据网友的反馈…

怎么邀请人加入组队_糖豆人:终极淘汰赛怎么玩?玩法技巧介绍

这几天玩糖豆人:终极淘汰赛的玩家都在问,这个游戏模式怎么玩,糖豆人终极淘汰赛是一款60人同台竞争的卡通吃鸡游戏。想要获胜还是有一定难度的,战神游戏加速器为大家带来这款游戏的基础操作和具体玩法,超低延迟极速体验…

2017年4月21号课堂笔记

2017年4月21号 星期五 空气质量&#xff1a;良 内容&#xff1a;XML&#xff0c;Dom4j解析XML文件&#xff0c;单例 一、XML 老师代码&#xff1a; <?xml version"1.0" encoding"UTF-8"?><!-- XML的注释xml是什么&#xff1f; 可扩展的标记语言…

服务器物理内存总是九十几,服务器物理内存使用率90以上

服务器物理内存使用率90以上 内容精选换一换开启弹性云服务器的虚拟内存后&#xff0c;会导致硬盘I/O性能下降&#xff0c;因此&#xff0c;平台提供的Windows弹性云服务器默认未配置虚拟内存。如果弹性云服务器内存不足&#xff0c;建议通过“变更规格”操作来扩大内存。如果业…

比较二进制_浮点数比较的精度问题

引言 先举个例子&#xff1a;#include <stdio.h>int main() {float a 0.1;float b 0.2;float c a b;if(c 0.3){printf("c 0.3n");}else{printf("0.1 0.2 ! 0.3n");}return 0; }如果变量a,b换0.75&#xff0c;0.5可以看出运行出c 1.25,说明浮…

open表和closed表_excel工作表合并,多文件数据一键合成

工作中 遇到十几个甚至几十个单独工作excel文件要合并成一个怎么办&#xff0c;难道还按照老办法复制工作表?几个还好说&#xff0c;遇到十几个几十个文件&#xff0c;手速不够快的宝宝心里苦。那么&#xff0c;有没有什么日常偷懒神技&#xff0c;一键合成多个excel文件&…

濡沫江湖一直显示获取服务器地址,濡沫江湖采集点坐标大全

濡沫江湖每个地图都有采集点&#xff0c;那么濡沫江湖采集点具体坐标是多少&#xff1f;下面9k9k小编就为大家整理带来濡沫江湖采集点坐标大全&#xff1a;小渔村(35,4)采集铜矿石、碎铁块小渔村(38&#xff0c;16)采集药草、杂草小渔村(14,35)采集亚麻、杂草小渔村(13,12)采集…

java第五次作业

《Java技术》第五次作业 &#xff08;一&#xff09;学习总结 1.在上周完成的思维导图基础上&#xff0c;补充本周的学习内容&#xff0c;对Java面向对象编程的知识点做一个全面的总结。 2.汽车租赁公司&#xff0c;出租汽车种类有客车、货车和皮卡三种&#xff0c;每辆汽车除了…

mysqld已删除但仍占用空间的_Windows 10删除备份文件方法

Windows具有许多内置备份功能&#xff0c;包括卷影副本&#xff0c;系统还原点和整个系统备份。尽管它们既不是最可靠也不是功能最丰富的备份解决方案&#xff0c;但它们确实提供了一种备份系统和个人数据的不错的方式。Windows内置备份工具的问题之一是它们几乎过于安静和方便…

服务器维修天长,台达精密空调服务天长市供电局

【IT168 厂商动态】项目背景&#xff1a;天长市供电局率属于安徽省供电局&#xff0c;主要负责其辖区内的电力生产与供应。本项目包括三个机房&#xff1a;南、北数据中心机房以及资料中心;台达风冷型精密空调为上述机房的IT设备运行提供7*24小时恒温恒湿高洁净度的运行环境&am…

终端主题_泛终端全渠道新模式中国移动5G泛智能终端渠道生态合作峰会开幕

11月20日&#xff0c;以“泛终端 全渠道 新业态 新模式”为主题的中国移动5G泛智能终端渠道生态合作峰会在广州成功举办。作为2020中国移动全球合作伙伴大会期间举办的重要主题峰会之一&#xff0c;该峰会吸引了超过100家终端、渠道等产业链合作伙伴&#xff0c;会议通过咪咕直…

jq中查找上级_【节能学院】电能管理系统在福州三岐小学项目中的设计及应用...

1项目概述该项目总投资约2.6亿元&#xff0c;建筑规模为4.8万㎡&#xff0c;建设地点在南屿镇葛岐村、晓岐村。项目设有教学楼A区、教学楼B区、教学楼C区、综合楼一区、综合楼二区、室内篮球场、室内游泳馆、足球场等。此电能管理系统为Acrel-3000V7.1系统&#xff0c;在结构设…

[HTML5amp;CSS3]Transform具体解释

Transform字面上就是变形&#xff0c;改变的意思。在CSS3中transform主要包含以下几种&#xff1a;旋转rotate、扭曲skew、缩放scale和移动translate以及矩阵变形matrix。以下我们一起来看看CSS3中transform的旋转rotate、扭曲skew、缩放scale和移动translate详细怎样实现。老样…

比亚迪定薪后多久给offer_比亚迪车主给爱车做四门隔音,没想到两年后肠子都悔青...

许多车主都有过这样的经历&#xff1a;总感觉爱车的静谧性不够如意&#xff0c;为了提升隔音效果改善驾乘质感&#xff0c;往往产生给爱车做一个全车隔音的冲动。只不过冲动归冲动&#xff0c;在着手对车子进行隔音改造工程前&#xff0c;一定要选择靠谱的隔音材料&#xff0c;…

Centos开机自己主动挂载windows中的ntfs磁盘

装了windows和centos双系统后&#xff0c;发如今centos中无法进入windows中的磁盘&#xff0c;更不要说查看磁盘里的文件了&#xff01; 原来默认情况下。centos不支持Widows NTFS硬盘分区读写&#xff0c;要想把NTFS格式的磁盘挂载到CentOS 以下须要安装第三方软件ntfs-3g。…

人工智能方向毕业设计_毕业季|广州美术学院视觉设计学院毕业设计展

视觉艺术设计学院成立于2010年9月&#xff0c;由广州美术学院最传统的装潢系和新兴的数码艺术设计系联合组建而成&#xff0c;2018年11月&#xff0c;艺术与科技专业并入学院。学院现拥有视觉传达设计、数字媒体艺术设计、动画、艺术与科技4个专业。视觉文化设计工作室 视觉文化…

江西住建云实名认证怎么弄_王者荣耀无限时间怎么弄 2020年无限时间账号

腾讯游戏都是有健康系统的&#xff0c;王者荣耀自然也不例外&#xff0c;王者还是第一批出健康系统的游戏&#xff0c;今年健康系统同时有时间限制和充值限制&#xff0c;未成年玩家一天最多只能玩1.5个小时&#xff0c;游戏现在有传闻无限时间账号&#xff0c;那么无限时间怎么…

coherence安装_在Oracle Coherence中分发Spring Bean

coherence安装本文展示了如何通过使用Oracle Coherence中的EntryProcessor和可移植对象格式&#xff08;POF&#xff09;功能来分发Spring Bean。 Coherence通过EntryProcessor API支持无锁编程模型。 此功能通过减少网络访问并在条目上执行隐式的低级锁定来提高系统性能。 此隐…