当前位置:文档之家› 模拟对象(Mock Object)测试驱动开发

模拟对象(Mock Object)测试驱动开发

在Java 阵营中主要的Mock 测试工具有jMock,MockCreator,MockRunner,EasyMock,MockMaker 等jMock 框架介绍总体上来说,jMock 是一个轻量级的模拟对象技术的实现。

它具有以下特点:可以用简单易行的方法定义模拟对象,无需破坏本来的代码结构表;可以定义对象之间的交互,从而增强测试的稳定性;可以集成到测试框架;易扩充;与大多数MOCK 框架一样,我们可以在IDE 中使用并进行开发。

本文以最常用的Eclipse 为例。

下载jMock/download.html在jMock 官方网站,我们可以下载当前稳定版本jMock2.5.1 。

配置类路径为了使用jMock 2.5.1,您需要加入下面的JAR 文件到当前的类路径。

jmock-2.5.1.jarhamcrest-core-1.1.jarhamcrest-library-1.1.jar图 1. 已添加到TestingExample 项目中jMock 的JAR 文件使用jMock 模拟接口我们首先必须引入jMock 的类,定义我们的测试类,创建一个Mockery 的对象用来代表上下文。

上下文可以模拟出对象和对象的输出,并且还可以检测应用是否合法。

1import org.jmock.Mockery;2import org.jmock.Expectations;34public class AJmockTestCase {56Mockery context = new Mockery();78}然后我们创建一个calcService 去模拟ICalculatorService 接口。

在这里我们以add() 方法为例,我们针对add() 方法定义预期值assumedResult 。

之后我们去调用add(1,1) 时,就可以得到预期值。

9// set up10final ICalculatorService calcService = context.mock(ICalculatorService.class);1112final int assumedResult = 2;1314// expectations15context.checking(new Expectations() {{16oneOf (calcService).add(1, 1); will(returnValue(assumedResult));17}});清单 3 和4 分别显示了ICalculatorService 和AJmockTestCase 的代码。

清单 3. ICalculatorService 代码18public interface ICalculatorService {1920public int add(int a, int b);2122}23清单 4. AJmockTestCase 代码24import org.jmock.Mockery;25import org.jmock.Expectations;2627public class AJmockTestCase {2829Mockery context = new Mockery();3031public void testCalcService() {3233// set up34final ICalculatorService calcService = context35.mock(ICalculatorService.class);3637final int assumedResult = 2;3839// expectations40context.checking(new Expectations() {41{42oneOf(calcService).add(1, 1);43will(returnValue(assumedResult));44}45});4647System.out.println(calcService.add(1, 1));4849}5051}在jMock 中,开发人员可以按照下面的语法定义预期值,从而实现更复杂的应用。

例如我们可以模拟底层驱动程序的输出,在上层应用程序中使用这些模拟数据。

具体可以参考jMock 的官方网站。

52invocation-count (mock-object).method(argument-constraints);53inSequence(sequence-name);54when(state-machine.is(state-name));55will(action);56then(state-machine.is(new-state-name));EasyMock 框架介绍在实际开发中,不少开发人员也使用EasyMock 来进行测试驱动开发。

EasyMock 具有以下的特点在运行时(runtime) 改变方法名或参数顺序,测试代码不会破坏;支持返回值和异常;对于一个或多个虚拟对象,支持检查方法调用次序;只支持Java 5.0 及以上版本;与大多数MOCK 框架一样,我们可以在IDE 中使用并进行开发。

本文以最常用的Eclipse 为例。

下载EasyMock在EasyMock 官方网站,我们可以下载当前稳定版本EasyMock2.4 。

配置类路径为了使用EasyMock 2.4,您需要加入下面的JAR 文件到当前的类路径。

easymock.jar图 2. 已添加到TestEasyMock 项目中EasyMock 的JAR 文件使用EasyMock 模拟接口清单 5. ILEDCard 代码57public interface ILEDCard {58String getMessage();5960void setMessage(String message);61}清单 6. LED 代码62public class LED {63private ILEDCard ledCard;6465public LED(ILEDCard ledCard) {66this.ledCard = ledCard;67}6869public String ShowMesage() {70return this.ledCard.getMessage();71}7273public void setMessage(String message) {74this.ledCard.setMessage(message);75}76}我们首先创建一个Mock 的对象mockLEDCard 来代表LED 卡的行为,并初始化LED 对象。

77protected void setUp() throws Exception {78super.setUp();79mockLEDCard = createMock(ILEDCard.class);80led = new LED(mockLEDCard);81}之后我们对ShowMessage 方法进行测试。

82public void testGetWord() {83expect(mockLEDCard.getMessage()).andReturn("This is a EasyMock Test!");84replay(mockLEDCard);8586led.ShowMesage();87verify(mockLEDCard);88}清单7 显示了完整的代码。

清单7. AEasyMockTestCase 代码89import static org.easymock.EasyMock.*;90import junit.framework.TestCase;9192public class AEasyMockTestCase extends TestCase {9394private LED led;95private ILEDCard mockLEDCard;9697protected void setUp() throws Exception {98super.setUp();99mockLEDCard = createMock(ILEDCard.class);100led = new LED(mockLEDCard);101}102103protected void tearDown() throws Exception {104super.tearDown();105}106107public void testGetWord() {108expect(mockLEDCard.getMessage()).andReturn("This is a EasyMock Test!");109replay(mockLEDCard);110111led.ShowMesage();112verify(mockLEDCard);113}114115public void testSetWord() {116mockLEDCard.setMessage("Another test");117replay(mockLEDCard);118119led.setMessage("Another test");120verify(mockLEDCard);121}122}通过上文对jMock 和EasyMock 的介绍,我们可以发现jMock 可以灵活的定义对象的行为。

例如mock.expects(once()).method("method2").with( same(b1), ANYTHING ).will(returnValue(method2Result)); 这点在EasyMock 里比较难于实现。

Rmock 及其它目前比较流行的mock 工具,还有RMock, 目前的版本的是2.0,当使用jUnit 开发测试用例时,它支持设置-修改-运行-验证这样的工作流。

它加强了基于交互和基于状态的测试,同时有更好的测试工作流定义。

Rmock 还可以使用DynamicSuite 来解决维护TestSuites 的问题。

市场上还有支持各种语言的Mock object 的框架,如pMock(Python),NMockLib(C#),Mocha(Ruby),JSMock(JavaScript),mockpp(C++) 。

结语在软件开发过程中,开发人员需要注重测试驱动开发,并利用模拟对象的技术来帮助进行测试。

许多开发人员不习惯于频繁编写测试。

即使需要编写测试,通常都是简单的进行主要功能测试。

相关主题