最近一直在着力推动部门单元测试工作,发现一些不规范的地方,特此尝试翻译下用户指南,方便大家参考。
原文参考:http://code.google.com/p/jmockit/
及 http://jmockit.googlecode.com/svn/trunk/www/tutorial/BehaviorBasedTesting.html
- 前言:开发者可以借助JMockit这个强大的测试辅助工具,利用mock 的API去解决平常在单元(或者集成)
测试中遇到的常见的可测试性问题。开发者同样可以很方便快捷的对final类、静态方法或者构造函数等进行mock模拟。在Jmcokit的世界中,没有
其他任何的限制。
Jmockit的API是极致简单、易用的。在编写测试代码时,不需要在测试代码中嵌入一些特定的方法或者注解,当然不包括一些必须的、有意义的方法和注解(还是有一定的必要).一般而言,使用JMockit的mock API可以使测试代码更结构化,可读性变得更强。
public void testDoOperationAbc(final DependencyXyz mock)
{
new NonStrictExpectations() {
AnotherDependency anotherMock;
{
anotherMock.doSomething("test"); result = 123;
}
};
new ServiceAbc().doOperation("some data");
new Verifications() {{
mock.complexOperation(true, anyInt, null); times = 1;
}};
}Mocked types
在Jmockit的工具箱中,Expectations 期望和Verifications
验证API对基于行为的单元测试提供了丰富的支持。这类型的测试的焦点是当前的单元测试代码如何和其他相依赖的单元进行交互。这些行为单元可以是定义在生
产环境中的class类,method方法,以及构造函数。
两个单元之间的交互通常以方法或者构造函数调用的形式出现。以参数和返回值的形式在当前单元和被依赖的单元之间传递构成的调用集合,定义了我们感兴趣的测
试代码行为。另外,对于给定的一个测试,可能需要判定调用集合在执行期间的执行顺序。注意,一个单元测试应该只是执行可测试的单元代码。这些实现所依赖的
关系不一定需要被执行,因为这些依赖并不是当前单元测试的一部分。所以,单元测试的目标应该是测试一些业务逻辑,这些逻辑是和真实行为需要依赖的外部关系
或者环境是隔离的。现在,对于给定的单元,我们一般不需要隔离所有的依赖,但需要隔离如下这些:1)一些依赖单元本身已经(或者将来会有,只是目前还没有
实现而已)拥有自己的单元测试。2)由于一些特殊原因,在测试环境中,一些并不是很容易快速的执行的单元(因为它们可能会写数据库或者发送邮件等等)。当
我们编写一个特殊的单元测试时,我们一般假设它对外部的依赖是满足一些期望的。如果不是的话,那就是外部的依赖本身所需要负的责任了,并应该满足这些期
望。
一般来说,在单元测试代码中,方法调用、构造函数以及那些相互依赖 /协助的单元都是我们mock的目标。
Mock技术提供了一种隔离外部依赖的可测试的单元机制。我们通过使用mocked声明,可以在指定的测试代码对一些特殊的依赖进行
mock模拟,也就是说,一个mocked类型,应该是单元测试中的一个依赖类型,这些类型可以是引用、接口、抽象类、具体的类、final 类等等。
默认情况下,被mock的类型的所有方法在测试期间都被
mock实现。如果一个mock类型被声明为类,那么除了java.lang.Object之外,该类的父类将被递归mock。因此,继承的方法也将自动
被mock。同样,对于声明为类的mock类型,其所有构造函数也将被
mock。甚至,无论方法或者构造函数的修饰符是否是private,stati,final,native等,这些方法和构造函数都会被mock掉,对
于mock类型来说,修饰符的定义变得如此不重要了。
在一个测试调用中,如果当一个方法或者构造函数被mock了,则其原始的实现代码将不会被执行,取而代之的是,可以通过
jmockit显式或者隐式指定测试调用。下面的示例代码,展示了一个mock类型的基本调用图。在这个指南中,我们通常使用类似这样的代码。当然,粗体
部分的注释才是我们现在的重点。
@Test
public void doBusinessOperationXyz()
{
...
new Expectations() // 一个称为期望的结构块
{
Dependency mockInstance; // "Dependency"是我们需要mock的类型
...
{
...
// "mockInstance" 是一个mock实例,在测试代码中自动提供如下类型的mock使用方法
mockInstance.mockedMethod(...);
...
}
};
...
}
就如我们即将在下面看到的一样,这里提供了好几种方式来声明mock类型,同样提供几种特殊修饰语法以满足一些特殊的测试mock。但大多数情况
下,例如变量都是通过一些特定的注解及注解本身的属性来指定mock,例如 @Mocked, @NonStrict,
@Injectable等等。这些注解标记可以在实例的域或者测试方法的参数中使用。
- Expectations(期望)
Expectations是一个给定的单元测试相关的mock方法/构造函数的调用集合。对于一个同样的方法或者构造函数,一个Expectations
可能会覆盖到多个不同调用,但是它不需要(不一定)覆盖到单元测试方法执行期间的所有调用(invocations)。一个特定的调用是否匹配给定的
expectation,不仅依赖方法/构造函数的签名,而且依赖运行时方面参数(aspects),例如被调用的方法类实例、参数值以及调用次数等等。
因此,对于给定的expectation,可以(可选)指定几种不同类型的匹配约束。
对于具有一个或者多个参数调用的情况,可能需要对每一个参数指定精确的参数值。例如,"test
string"可以指定为一个字符串参数,从而匹配到那些具有相应的精确的参数调用的expectation。正如我们后面将所见到的一样,我们可以通过
指定更多相关的约束来匹配一个具有不同参数值的集合,而不是指定精确的参数值。
下面的例子展示了类Dependency的方法someMethod(int, String)的一个期望(expectation
),这个期望是通过指定严格(精确)的参数值来匹配这个方法的调用。值得注意的是,对于这个mock方法,这个期望本身就是一个特定的隔离调用。在测试代
码中,没有什么特殊的API的参与其中。但是,在我们所感兴趣的测试中,这个调用不能认为是一个真实的调用。它在这里的目的唯一作用是可以用于指定
expectation而已。
@Test
public void doBusinessOperationXyz()
{
...
new Expectations()
{
Dependency mockInstance;
...
{
...
// 一个mock实例的mock方法
mockInstance.someMethod(1, "test");
...
}
};
//这里应该是一个单元测试方法调用,这个调用可能匹配(也可能不匹配)上面指定的expectations
}
在之后我们理解了recording、
replaying、
verifying调用的差异后,我们将看到更多的
expectations。
- Record-Replay-Verify模型
任何一个测试至少可以划分三个相互独立的阶段,这些阶段将按顺序执行,一次执行一个阶段,例如下面的示例:
@Test
public void someTestMethod()
{
// 1. 准备阶段:测试执行之前所需要的所有东西都可以编写在这里
...
// 2. 单元测试代码在这里执行,通常是通过调用public方法来执行
...
// 3. 验证阶段:验证上面所执行的单元测试代码真正执行了其业务逻辑
...
}
首先,我们有一个准备阶段,单元测试代码所需要的对象和数据都可以在这里创建或者从其他地方加载进来。之后,测试的代码被执行。最后,测试结果和期望结果进行比较。
这个著名的三阶段也叫做Arrange, Act, Assert
语法,或者简称为"AAA",不同的词语而已,意思实际就是一样。
在基于行为的测试上下文中,通过使用 mock类型(以及他们对应的mock实例),我们可以辨别出来下面的交互流程直接对应上面描述的哪些测试阶段。
(1) Record(记录)阶段:在这里将记录下哪些调用会被期望执行,这些都是发生在测试的准备阶段,而且在真正测试代码执行调用之前。
(2) Replay(重播)阶段:我们感兴趣的mock
调用将在这里有机会被执行,就好像真正的单元测试代码被执行一样。这些在Record阶段记录下来的 mock方法
/构造函数调用将在这里重播(执行),尽管这些mock调用在record和replay阶段通常不是一对一对应的。
(3)Verify(验证)阶段:所有的真实调用应该在这里和期望值进行校验,这些动作发生在测试验证阶段。
利用JMockit工具来编写基于行为的测试代码,通常符合下面的经典模板:
import mockit.*;
... other imports ...
public class SomeTest
{
// 零个或者更多的mock 属性, 这些属性对于整个类的所有测试方法来说是通用的。
@Mocked Collaborator mockCollaborator;
@NonStrict AnotherDependency anotherDependency;
...
@Test
public void testWithRecordAndReplayOnly(mock parameters)
{
// 如果这里需要测试前的准备,可以在这里执行,但对于Jmockit 来说,对此没特别要求。当然这里也可以为空。
new Expectations() // 一个期望块
{
// 零个或者多个局部 mock 属性域
{
// 一个或者多个mock对象(类型)的调用,这些调用会被Expectations记录(Recorded)下来
//一些没有被mock的方法、对象类型等同样可以在这个期望块里面调用
}
};
// 单元测试代码真正业务逻辑在此执行
// 如果需要,可以在这里进行验证代码编写,当然可以利用JUnit/TestNG 断言
}
@Test
public void testWithReplayAndVerifyOnly(mock parameters)
{
// 如果这里需要测试前的准备,可以在这里执行,但对于Jmockit 来说,对此没特别要求。当然这里也可以为空。
// 单元测试代码真正业务逻辑在此执行
new Verifications() {{ // 一个验证块
// 一个或者多个mock对象(类型)的调用,这些调用用于验证结果是否正确
//一些没有被mock的方法、对象类型等同样可以在这个验证块里面调用
}};
// 如果需求,这里可以添加其他额外的验证代码,
// 当然,这些验证可以编写在这里,也可以在Verifications块之前
}
@Test
public void testWithBothRecordAndVerify(mock parameters)
{
//如果这里需要测试前的准备,可以在这里执行,但对于Jmockit 来说,对此没特别要求。当然这里也可以为空。
new NonStrictExpectations() { // 同样是一个期望块
//零个或者多个局部 mock 属性域
{
// 一个或者多个mock对象(类型)的调用,这些调用会被Expectations记录(Recorded)下来
}
};
// 单元测试代码真正业务逻辑在此执行
new VerificationsInOrder() {{ // 同样是一个验证块
// 一个或者多个mock对象(类型)的调用,这些调用将期望按照特定的顺序进行比较。
}};
// 如果需求,这里可以添加其他额外的验证代码,
// 当然,这些验证可以编写在这里,也可以在Verifications块之前
}
在上面的模板中,还存在一些其他额外的变量,但是从本质上来说,这些expectation
期望块是属于Record阶段的,而且在单元测试真正业务逻辑执行前被执行,当然,自然而然,verification
验证块是属于验证阶段的。一个测试方法可以包含任意数量(含零个)的期望块,验证块也是一样。
事实上,我们可以利用现代JAVA IDE工具的高级功能"代码折叠",对匿名内部类进行折叠展示。下面图片显示了再IntelliJ IDEA中的折叠效果:
分享到:
相关推荐
java平台的API规范,标准版翻译校对版本,这是好心人翻译的,我认为目前是最好的中文api,分享下信息,chm版本
用户手册介绍了基本的用户界面和JaamSim提供的基本实体。这些特征对于这个软件创建的所有仿真模型来说都是常见的。还包括一些特定应用程序的文档说明,比如Ausenco运输物流模拟器(TLS)对应的相应的模块就能在手册中...
《校对能手》是一款中文文稿校对软件。可以快速对中文文档资料进行校对,检查出可能存在的差错,列出勘误表,供改稿时参考。同时,还有姓名筛查、人名地名索引自动编排、多能字词典、中文排序等功能。特别适用于快速...
《编辑助手》又名“校对能手”是一款中文文稿校对软件。在各种文稿的起草、修改、抄写、打字、排版过程中,难免出现各种差错,手工校对检查费时费力,往往还会有所遗漏。本软件针对上述问题,可以快速对中文文档资料...
自动控制原理实验指南(已校对)排版 实验注意事项 (一)“综合实验台” 及其挂箱初次使用或较长时间未用时,实验前务必对“实验台”及其挂箱进行全面检查和单元环节调试。 (二)实验前,务必设置系统工作状态,并按...
MISRA C 2012规范—中文精校版,精确翻译,校对。 220页内容,精心准备,望好评! MISRA C 2012规范—中文精校版,精确翻译,校对。 220页内容,精心准备,望好评! MISRA C 2012规范—中文精校版,精确翻译,校对。...
黑马校对软件百度网盘下载地址,精确校对领导人姓名、职务和领导人排序错误。 精确校对涉及台湾和其他敏感的政治性错误。 即时更新的、可自定义的领导人职务库。校对插件 直接嵌入在Acrobat中校对PDF文件。可把校对...
满足markdown格式的Spring官方文档中文翻译版,一手信息才能掌握Spring!
更有解释、翻译、词典以及英文写作辅助等实用功能来辅助用户快速改正错误,能极大地提高用户写作准确率的成文质量,是非常理想的英文写作和校对助手以及单词检查软件,除此之外易改还提供1Checker Word插件,支持MS ...
我的专业工作案例可以从以下链接下载: ...需要预先安装同一目录下...中英文文本自动摘要、自动校对、自动分类、相关性与相似性聚类、主题词与标签自动生成、微博(短文本)聚类和情感分析。我的研究成果,欢迎下载传播。
因文件上传不能超50M,因此再继续上传3个校对库文件。将3个校对库内的文件全部复制到\Winwps2000带校对压缩包你即可使用!
Word语音打字校对专家是一款针对Word文档语音输入识别和语音合成软件,能在你键盘输入的同时把你在Word中所输入的字符或汉字读出来,这样就可以大幅度提高工作效率了,这点对于用五笔或其它形码的朋友来说就更显得...
找出所有的红色巧克力豆: 关于索引查询和全表扫描翻译人:姚稼接 校对人,lvan.Yu 原文地址:https://use-the-index-luke.com/
基于深度学习的中文文本自动校对研究与实现.pdf
基于中文分词的文本自动校对,颜军,潘昊,中文文本自动校对是自然语言处理领域中有着广阔应用前景的一个研究方向。本文依据中文分词的结果以及常见错误的特点,结合三元字
1. 29244-g00,为2019年6月份3GPP提交的标准文档。...2. 文档为本人下载网络上提供,后续因工作需要进行深入学习,里面的翻译已校对(实话前人提供的版本,就是一个google翻译的结果),并做了理解标注。
本人翻译的ITIL 4 FOUNDATION文档
针对句法与短语的英语翻译校对系统重视精准度校准,无法解决连贯性差的问题,提出了基于改进短语翻译模型的智能校对系统。...通过测试结果表示,系统能够满足用户对翻译的校对需求,提高校对效率。
本书目前只有翻译87章,尚在更新,需完整版可以去看看十积分的这个 http://download.csdn.net/download/qq_39419087/9977947 2014年3月,编辑和Dennis签订中文版授权出版协议 2014年6月,Archer经过认真的考虑,...
选中第三方输入法,它就可以在使用用户自己安装的任何一种汉字输入法时,汉字上屏以后读出语音提示。 声音 用来设置有关声音的各种功能。在语音库中选择男声或女声(以后的升级版本提供此项选择,本版本只有男声一...