首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

easymock课程-strict和nice

2012-08-08 
easymock教程-strict和nice??? 在easymock的使用过程中,当创建mock对象时,我们会遇到 strict mock和nice m

easymock教程-strict和nice

??? 在easymock的使用过程中,当创建mock对象时,我们会遇到 strict mock和nice mock的概念。

?

??? 比如创建mock对象我们通常使用EasyMock.createMock(),但是我们会发现easymock同时提供了两个类似的方法:

easymock课程-strict和nice?EasyMock.createNiceMock()
easymock课程-strict和nice?EasyMock.createStrictMock()

??? 类似的在创建MocksControl时,除了通常的EasyMock.createControl() 外,easymock也同时提供两个类似的方法:

easymock课程-strict和nice?EasyMock.createNiceControl()?
easymock课程-strict和nice?EasyMock.createStrictControl()?

?

??? 我们来看看strict和nice有什么作用。参考easymock的javadoc,我们对比createMock()和createStrictMock():


?EasyMock.createMock():???????? ?Creates a mock object that implements the given interface, order checking is disabled by default.
?EasyMock.createNiceMock() : Creates a mock object that implements the given interface, order checking is enabled by default.

?

??? 发现strict mock方式下默认是开启调用顺序检测的,而普通的mock方式则默认不开启调用顺序检测。

?

??? 再看一下createNiceMock():

?

Creates a mock object that implements the given interface, order checking is disabled by default, and the mock object will return 0, null or false for unexpected invocations.

?

??? 和createMock()相同的是默认不开启调用顺序检测,另外有一个非常有用的功能就是对于意料之外的调用将返回0,null 或者false.之所以说有用,是因为在我们的实际开发过程中,有时候会有这样的需求:对于某个mock对象的调用(可以是部分,也可以是全部),我们完全不介意调用细节,包括是否调用和调用顺序,参数,返回值,我们只要求mock对象容许程序可以继续而不是抛出异常报告说 unexpected invocations 。nice mock在这种情况下可以为我们节省大量的工作量,非常方便。

?

????我们来看一个简单的实际使用的例子,假设我们有一个Business类,依赖于两个service 接口:

?

??? 先看只调用一个依赖的情况,注意在record阶段service1.method2()和service1.method1()的顺序和business.executeService1()方法中的实际调用顺序是故意设置为不同的。

easymock课程-strict和niceeasymock课程-strict和nice????public?class?Business?{
easymock课程-strict和nice????????private?Service1?service1;
easymock课程-strict和nice
easymock课程-strict和nice????????private?Service2?service2;
easymock课程-strict和nice????????
easymock课程-strict和niceeasymock课程-strict和nice????????public?void?executeService1()?{
easymock课程-strict和nice????????????service1.method1();
easymock课程-strict和nice????????????service1.method2();
easymock课程-strict和nice????????}
easymock课程-strict和nice????????
easymock课程-strict和niceeasymock课程-strict和nice????????public?void?executeService1And2()?{
easymock课程-strict和nice????????????service1.method1();
easymock课程-strict和nice????????????service1.method2();
easymock课程-strict和nice????????????
easymock课程-strict和nice????????????service2.method3();
easymock课程-strict和nice????????????service2.method4();
easymock课程-strict和nice????????}
easymock课程-strict和nice
easymock课程-strict和niceeasymock课程-strict和nice????????public?void?setService1(Service1?service1)?{
easymock课程-strict和nice????????????this.service1?=?service1;
easymock课程-strict和nice????????}
easymock课程-strict和nice
easymock课程-strict和niceeasymock课程-strict和nice????????public?void?setService2(Service2?service2)?{
easymock课程-strict和nice????????????this.service2?=?service2;
easymock课程-strict和nice????????}
easymock课程-strict和nice????}
easymock课程-strict和nice
easymock课程-strict和niceeasymock课程-strict和nice????private?interface?Service1?{
easymock课程-strict和nice
easymock课程-strict和nice????????public?void?method1();
easymock课程-strict和nice
easymock课程-strict和nice????????public?void?method2();
easymock课程-strict和nice????}
easymock课程-strict和nice
easymock课程-strict和niceeasymock课程-strict和nice????private?interface?Service2?{
easymock课程-strict和nice
easymock课程-strict和nice????????public?void?method3();
easymock课程-strict和nice
easymock课程-strict和nice????????public?void?method4();
easymock课程-strict和nice????}


1. 普通mock

easymock课程-strict和nice????@Test
easymock课程-strict和niceeasymock课程-strict和nice????public?void?testMock()?{
easymock课程-strict和nice????????Business?business?=?new?Business();
easymock课程-strict和nice????????Service1?service1?=?EasyMock.createMock("service1",?Service1.class);
easymock课程-strict和nice????????business.setService1(service1);
easymock课程-strict和nice????????
easymock课程-strict和nice????????service1.method2();
easymock课程-strict和nice????????EasyMock.expectLastCall();
easymock课程-strict和nice????????service1.method1();
easymock课程-strict和nice????????EasyMock.expectLastCall();
easymock课程-strict和nice
easymock课程-strict和nice????????
easymock课程-strict和nice????????EasyMock.replay(service1);
easymock课程-strict和nice????????business.executeService1();
easymock课程-strict和nice????????EasyMock.verify(service1);
easymock课程-strict和nice????}
easymock课程-strict和nice


??? 测试案例可以通过,说明EasyMock.createMock()的确是不检测方法的调用顺序。

2. strict mock

easymock课程-strict和nice????@Test
easymock课程-strict和niceeasymock课程-strict和nice????public?void?testStrictMock()?{
easymock课程-strict和nice????????Business?business?=?new?Business();
easymock课程-strict和nice????????Service1?service1?=?EasyMock.createStrictMock("service1",?Service1.class);
easymock课程-strict和nice????????...
easymock课程-strict和nice????}
easymock课程-strict和nice
easymock课程-strict和nice

??? 案例失败,错误信息如下
java.lang.AssertionError:
? Unexpected method call service1.method1():
??? service1.method2(): expected: 1, actual: 0
?at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:45)
?at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
?at net.sourcesky.study.easymock.tutorial.$Proxy4.method1(Unknown Source)
?at net.sourcesky.study.easymock.tutorial.OrderTest$Business.executeService1(OrderTest.java:14)
?at net.sourcesky.study.easymock.tutorial.OrderTest.testStrictMock(OrderTest.java:79)
?......

??? 说明strict mock下,easymock检测到了实际调用时的顺序和预期的不同。

3. nick mock

easymock课程-strict和nice????@Test
easymock课程-strict和niceeasymock课程-strict和nice????public?void?testNiceMock()?{
easymock课程-strict和nice????????Business?business?=?new?Business();
easymock课程-strict和nice????????Service1?service1?=?EasyMock.createNiceMock("service1",?Service1.class);
easymock课程-strict和nice??????? ...
easymock课程-strict和nice????}

??? 测试案例可以通过,而且如果是nick mock的话,record阶段可以简化:

easymock课程-strict和nice????@Test
easymock课程-strict和niceeasymock课程-strict和nice????public?void?testNiceMockSimplify()?{
easymock课程-strict和nice????????Business?business?=?new?Business();
easymock课程-strict和nice????????Service1?service1?=?EasyMock.createNiceMock("service1",?Service1.class);
easymock课程-strict和nice????????business.setService1(service1);
easymock课程-strict和nice????????
easymock课程-strict和nice????????EasyMock.replay(service1);
easymock课程-strict和nice????????business.executeService1();
easymock课程-strict和nice????????EasyMock.verify(service1);
easymock课程-strict和nice????}

??? 这个简化版本的测试案例也是可以通过的。

?

??? 上述的测试案例验证了strict mock和nice mock的基本使用,对于同一个mock对象,strict模式下多个方法之间的调用顺序在record阶段和replay阶段下是需要保持一致的。但是故事并不是到此结束,更有意思的内容在后面:如果出现多个mock对象,那么这些不同mock对象的方法之间,他们的调用顺序是否检测?普通mock和nice mock模式下自然是不会检测顺序,但是strict模式下呢?

?

??? 我们来看需要测试的方法executeService1And2(),这个方法会依次调用service1和service2的方法。使用easymock测试这个方法,注意我们在record阶段依然故意将方法的调用顺序设置为和实际不同。

?

1. 不使用control,直接创建两个strict mock对象

easymock课程-strict和nice????@Test
easymock课程-strict和niceeasymock课程-strict和nice????public?void?testWithoutControlInWrongOrder()?{
easymock课程-strict和nice????????Business?business?=?new?Business();
easymock课程-strict和nice????????Service1?service1?=?EasyMock.createStrictMock("service1",?Service1.class);
easymock课程-strict和nice????????Service2?service2?=?EasyMock.createStrictMock("service2",?Service2.class);
easymock课程-strict和nice????????business.setService1(service1);
easymock课程-strict和nice????????business.setService2(service2);
easymock课程-strict和nice????????
easymock课程-strict和nice????????service2.method3();
easymock课程-strict和nice????????EasyMock.expectLastCall();
easymock课程-strict和nice????????service1.method1();
easymock课程-strict和nice????????EasyMock.expectLastCall();
easymock课程-strict和nice????????
easymock课程-strict和nice????????EasyMock.replay(service1,?service2);
easymock课程-strict和nice????????business.executeService1And2();
easymock课程-strict和nice????????EasyMock.verify(service1,?service2);
easymock课程-strict和nice????}

??? 这个测试案例,出于意外的,通过了。easymock并没有检测service1.method1()和service2.method3()这两个方法的调用顺序。


2. 使用strict control创建两个strict mock对象

easymock课程-strict和nice????@Test
easymock课程-strict和niceeasymock课程-strict和nice????public?void?testWithStrictControlInWrongOrder()?{
easymock课程-strict和nice????????Business?business?=?new?Business();
easymock课程-strict和nice????????IMocksControl?mocksControl?=?EasyMock.createStrictControl();
easymock课程-strict和nice??????? ...
easymock课程-strict和nice????}

??? 案例失败,错误信息为:

java.lang.AssertionError:
? Unexpected method call service1.method1():
??? service2.method3(): expected: 1, actual: 0
?at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:45)
?at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:73)
?at net.sourcesky.study.easymock.tutorial.$Proxy4.method1(Unknown Source)
?at net.sourcesky.study.easymock.tutorial.OrderTest$Business.executeService1And2(OrderTest.java:19)
?at net.sourcesky.study.easymock.tutorial.OrderTest.testWithStrictControlInWrongOrder(OrderTest.java:218)
?......

?

??? OK,easymock终于检测到service1.method1()和service2.method3()这两个方法的调用顺序和期望的不一致了。

?

??? 解释一下,EasyMock.createStrictMock()方法实际上内部是生成一个新的strict control,然后再创建mock对象。

??????? Service1 service1 = EasyMock.createStrictMock("service1", Service1.class);
??????? Service2 service2 = EasyMock.createStrictMock("service2", Service2.class);

?

??? 这里实际是创建了两个strict control,而easymock是不会跨control进行顺序检测的。在实际使用过程中,我们会有大量的场景需要检测多个mock之间的调用顺序(按说如果没有特殊要求,一般的测试场景默认都应该如此),这种情况下就必须使用control, 而且必须是同一个strict control才能满足要求。

?

??? 教程后面的最佳实践中有一条就是推荐使用mock control,可以跨mock对象检测方法调用顺序是一个重要原因。

?

?

热点排行