声明:
Author:赵志乾
Date:2017-7-30
Declaration:All Right Reserved!!!
以发布、订阅消息系统为例,写一个mock对象。发布者会向0个或多个订阅者发布消息,而我们想对同订阅者存在交互的发布者进行测试。订阅者的接口如下:
interface Subscriber { void receive(String message); }
接下来我们会测试发布者向一个已注册的订阅者发送消息这一动作。为了测试发布者同订阅者之间的交互,我们需要mock了一个订阅者对象。
1、设置类路径
要使用JMock2.6.1,需要将下面的JAR包放到类路径中:
- jmock-2.6.1.jar
- hamcrest-core-1.3.jar
- hamcrest-library-1.3.jar
- jmock-junit4-2.6.1.jar
2、写一个测试用例
首先需要导入JMock类,定义测试夹具类,并创建一个Mockery(代表发布者所处的上下文)。该上下文能够模拟出同发布者交互的对象(在本例当中指订阅者)并检验在测试过程使用的正确性。
import org.jmock.Expectations; import org.jmock.Mockery; import org.jmock.integration.junit4.JMock; import org.jmock.integration.junit4.JUnit4RuleMockery; public class PublisherTest { @Rule public JUnitRuleMockery context = new JUnitRuleMockery(); ... }
注意:上面代码实例需要使用JMock2.6.0和JUnit4.7以上的版本。如果我们使用的是JUnit4以及一个老版本的JMock,我们可以使用一个JMock测试运行器来做(如下),只不过它相对于上面的规则机制而言,灵活性较差。
import org.jmock.Expectations; import org.jmock.Mockery; import org.jmock.integration.junit4.JMock; import org.jmock.integration.junit4.JUnit4RuleMockery; @RunWith(JMock.class) public class PublisherTest { Mockery context = new JUnit4Mockery(); ... }
下面我们开始写想要执行测试方法
@Test public void oneSubscriberReceivesAMessage() { ... }
接着写测试方法的方法体。
首先设置我们的测试执行时所处的上下文。再创建我们要测试的发布者对象。mock出来的订阅者需要能够接收发布者发布的消息,为此,通过发布者对订阅者进行注册。最后创建了一个要发布的消息对象。
final Subscriber subscriber = context.mock(Subscriber.class); Publisher publisher = new Publisher(); publisher.add(subscriber); final String message = "message";
之后,在mock出的订阅者上定义预期,该预期指定了在测试期间想在该对象上调用的方法。我们期望调用一次带有单个参数的receive方法。定义预期如下:
context.checking(new Expectations() {{ oneOf (subscriber).receive(message); }});
然后执行我们想要测试的代码,
publisher.publish(message);
测试代码执行完后,会验证mock出来的订阅者是否像预期的一样被调用。如果预期调用没有完成,测试就会失败。在测试当中,mock对象上预期的验证工作会由JMock测试运行器自动执行,无需我们显式验证。
3、完成的测试代码如下:
import org.jmock.integration.junit4.JMock; import org.jmock.integration.junit4.JUnit4Mockery; import org.jmock.Expectations; @RunWith(JMock.class) public class PublisherTest { Mockery context = new JUnit4Mockery(); @Test public void oneSubscriberReceivesAMessage() { // set up final Subscriber subscriber = context.mock(Subscriber.class); Publisher publisher = new Publisher(); publisher.add(subscriber); final String message = "message"; // expectations context.checking(new Expectations() {{ oneOf (subscriber).receive(message); }}); // execute publisher.publish(message); } }