官方入门例子:http://www.jmock.org/getting-started.html
jmock可以模拟对象,常用于单元测试,与junit配合使用
如下例子:
实现一个信息打印的例子
首先是一个获取信息的类,一会就是使用jmock来虚拟这个类出来,现在这个类并没有实现,我们只给它定义出接口:
public interface MessageProvider {
//获取数据信息
public String getMessage();
}
好,下来就是打印类,该打印类先通过MessageProvider获取到数据再打印,代码如下:
public class MsgPrint {
String message = "";
public MsgPrint(MessageProvider provider) {
this.message= provider.getMessage();
}
public void print() {
//打印
System.out.println(message);
}
}
嗯,整个过程我们并没有实现MessageProvider,但是让我们先来跑通整个过程,进行我们的测试吧。
import org.jmock.Mockery;
import org.jmock.Expectations;
class PrintTest extends TestCase {
Mockery context = new Mockery();
public void testGetMessage() {
// 模拟MessageProvider对象
final MessageProvider provider = context.mock(MessageProvider.class);
final String message = "message";
// expectations
context.checking(new Expectations() {{
one (provider).getMessage();
will (returnValue(message));
}});
//调用测试,通过上面的模拟,provider已经是一个有实现的对象
MsgPrint printer= new MsgPrint(provider);
printer.print();
}
}
快速上手教程
一个消息发布与订阅系统的例子
此处,我们通过一个简单的示例来为读者示范jMock 的使用方法。这是一个简化了的消息发布与订阅系统的例子,是典型的Observer 模式,熟悉设计模式的读者对此一定不会陌生。我们用Publisher来代表消息发送方,用Subscriber 来代表消息订阅方(即接收方)。以下是Subscriber 接口的定义:
interface Subscriber { |
一个Publisher 可以将消息(此处以String 类型的字符串对象来表达)发送给0 个或多个Subscriber 的具体实现类。而Subscriber 的具体实现类则通过Publisher 提供的接口向其注册。在本例中,我们旨在测试Publisher 的执行逻辑,而不关心具体Subscriber 的实现逻辑。为此,我们需要构造一个Mock 对象用以模拟Subscriber 的行为。然后将其注册到Publisher 里。
首先,我们必须引入jMock 的相关包,并构造一个Mockery 对象。该对象是jMock 提供Mock 能力的统一入口,后面我们将利用它来模拟Subscriber 的行为,并用它来检验Publisher 对Subscriber的模拟对象调用过程的正确性。
import org.jmock.Expectations; |
public void testOneSubscriberReceivesAMessage() { |
final Subscriber subscriber = context.mock(Subscriber. |
context.checking(new Expectations() {{ |
publisher.publish(message); |
此处,我们再次利用了Mockery 实例,用以验证Publisher 对Subscriber 的调用是否如期执行。假如调用并非如预期的那样,则测试会失败。
以下是完整的示例代码:
import org.jmock.Mockery; |
... 创建Mockery对象 ... |
Expectations用法简介
jMock 的Expectations 具有如下结构:
invocation-count (mock-object).method(argumentconstraints); |
其中,mock-object 是事先构造好的Mock 对象,如前例的Subscriber;而method 则是即将接受调用的Mock 对象的方法名称,如前例Subscriber 接口的receive 方法。除去invocation-count 和mock-object 外,后续内容都是可选的。同时,你也可以根据实际需要,为某个Expectation 追加多个inSequence、when、will 和then 子句。
invocation-count
代表期望的方法调用次数,jMock 提供了表达方法调用次数的多种手段,如表18-1 所示:
表18-1 jMock提供的方法调用次数的表达形式
|
argument-constraints
代表方法调用传入参数的约束条件,可以是精确匹配的条件,如下例所示,calculator 的add 方
法只期望接受两个整数1 作为参数:
one (calculator).add(1, 1); |
allowing (calculator).add(with(any(int.class)), |
除any 外,jMock 还提供了各种其他形式的参数约束子句,如表18-2 所示:
表18-2 jMock提供的参数约束子句
|
will
代表方法调用返回情况的约束条件,jMock 提供的返回约束如表18-3 所示:
表18-3 jMock提供的返回约束
|
inSequence
用于定义多个方法调用的执行顺序,inSequence 子句可以定义多个,其在测试代码中出现的次序,便是方法调用的执行顺序。为了定义一个新的顺序,首先需要定义一个Sequence 对象,如下所示:
final Sequence sequence-name = context.sequence("sequencename"); |
one (turtle).forward(10); inSequence(drawing); |
when和then
用于定义方法仅当某些条件为true 的时候才调用执行,从而进一步对Mock 对象的调用情况进行约束。在jMock 中,这种约束是通过状态机的形式来达成的。首先,我们需要定义一个状态机实例,其中的初始状态(initial-state)是可选的:
final States state-machine-name = |
final States pen = context.states("pen").startsAs("up"); |
本文通过两个实战案例介绍jMock框架的基本用法,包括如何模拟对象以进行单元测试,以及如何利用Expectations特性来定义测试场景。




1253

被折叠的 条评论
为什么被折叠?



