jmock25基本教程.docx

上传人:b****3 文档编号:3651004 上传时间:2022-11-24 格式:DOCX 页数:18 大小:22.27KB
下载 相关 举报
jmock25基本教程.docx_第1页
第1页 / 共18页
jmock25基本教程.docx_第2页
第2页 / 共18页
jmock25基本教程.docx_第3页
第3页 / 共18页
jmock25基本教程.docx_第4页
第4页 / 共18页
jmock25基本教程.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

jmock25基本教程.docx

《jmock25基本教程.docx》由会员分享,可在线阅读,更多相关《jmock25基本教程.docx(18页珍藏版)》请在冰豆网上搜索。

jmock25基本教程.docx

jmock25基本教程

jmock2.5基本教程 

目录 

第0章概述 

第1章jmock初体验 

第2章期望 

第3章返回值 

第4章参数匹配 

第5章指定方法调用次数 

第6章指定执行序列 

第7章状态机 

第0章概述 

现在的dev不是仅仅要写code而已,UT已经变为开发中不可缺少的一环。

JUnit的出现给javaer的UT编写提供了巨大的便利。

但是JUnit并没有解决所有的问题。

 

当我们要测试一个功能点的时候,需要把不需要我们关注的东西隔离开,从而可以只关注我们需要关注的行为。

 

jmock通过mock对象来模拟一个对象的行为,从而隔离开我们不关心的其他对象,使得UT的编写变得更为可行,也使得TDD变得更为方便,自然而然的,也就成为敏捷开发的一个利器。

 

可以到http:

//www.jmock.org/download.html下载jmock. 

添加jar到classpath。

 

添加的时候,注意把JUnit4的order放到最后。

因为junit4它自己带了一个Hamcrestjar。

 

要是不注意顺序的话,有可能报 

java.lang.SecurityException:

class"org.hamcrest.TypeSafeMatcher"'ssignerinformationdoesnotmatchsignerinformationofotherclassesinthesamepackage。

 

Note:

 

这里的类定义用来演示如何使用jmock,所以都是定义为public的。

Java代码  

1.public class UserManager {  

2.  

3.    public AddressService addressService;  

4.  

5.    public Address findAddress(String userName) {  

6.        return addressService.findAddress(userName);  

7.    }  

8.  

9.    public Iterator

 findAddresses(String userName) {  

10.        return addressService.findAddresses(userName);  

11.    }  

12.}  

我们有一个UserManager,要测试它的方法,但是,UserManager是依赖于AddressService的。

这里我们准备mock掉AddressService。

 

第1章jmock初体验 

这个例子的作用在于像一个传统的helloworld一样,给大家一个简明的介绍,可以有一个感觉,jmock可以做什么。

 

AddressService本身太复杂,很难构建,这个时候,jmock出场了。

Java代码  

1.@Test  

2.public void testFindAddress() {  

3.  

4.    // 建立一个test上下文对象。

   

5.    Mockery context = new Mockery();  

6.  

7.    // 生成一个mock对象   

8.    final AddressService addressServcie = context  

9.            .mock(AddressService.class);  

10.  

11.    // 设置期望。

   

12.    context.checking(new Expectations() {  

13.        {  

14.            // 当参数为"allen"的时候,addressServcie对象的findAddress方法被调用一次,并且返回西安。

   

15.            oneOf(addressServcie).findAddress("allen");  

16.            will(returnValue(Para.Xian));  

17.        }  

18.    });  

19.  

20.    UserManager manager = new UserManager();  

21.  

22.    // 设置mock对象   

23.    manager.addressService = addressServcie;  

24.  

25.    // 调用方法   

26.    Address result = manager.findAddress("allen");  

27.  

28.    // 验证结果   

29.    Assert.assertEquals(Result.Xian, result);  

30.  

31.}  

那么这里做了什么事情呢?

 

1首先,我们建立一个test上下文对象。

 

2用这个mockerycontext建立了一个mock对象来mockAddressService. 

3设置了这个mockAddressService的findAddress应该被调用1次,并且参数为"allen"。

 

4生成UserManager对象,设置addressService,调用findAddress。

 

5验证期望被满足。

 

基本上,一个简单的jmock应用大致就是这样一个流程。

 

最显著的优点就是,我们没有AddressService的具体实现,一样可以测试对AddressService接口有依赖的其他类的行为。

也就是说,我们通过mock一个对象来隔离这个对象对要测试的代码的影响。

 

由于大致的流程是一样的,我们提供一个抽象类来模板化jmock的使用。

Java代码  

1.public abstract class TestBase {  

2.  

3.    // 建立一个test上下文对象。

   

4.    protected Mockery context = new Mockery();  

5.  

6.    // 生成一个mock对象   

7.    protected final AddressService addressServcie = context  

8.            .mock(AddressService.class);  

9.  

10.    /**  

11.     * 要测试的userManager.  

12.     * */  

13.    protected UserManager manager;  

14.  

15.    /**  

16.     * 设置UserManager,并且设置mock的addressService。

  

17.     * */  

18.    private void setUpUserManagerWithMockAddressService() {  

19.        manager = new UserManager();  

20.        // 设置mock对象   

21.        manager.addressService = addressServcie;  

22.    }  

23.  

24.    /**  

25.     * 调用findAddress,并且验证返回值。

  

26.     *   

27.     * @param userName  

28.     *            userName  

29.     * @param expected  

30.     *            期望返回的地址。

  

31.     * */  

32.    protected void assertFindAddress(String userName, Address expected) {  

33.        Address address = manager.findAddress(userName);  

34.        Assert.assertEquals(expected, address);  

35.    }  

36.  

37.    /**  

38.     * 调用findAddress,并且验证方法抛出异常。

  

39.     * */  

40.    protected void assertFindAddressFail(String userName) {  

41.        try {  

42.            manager.findAddress(userName);  

43.            Assert.fail();  

44.        } catch (Throwable t) {  

45.            // Nothing to do.   

46.        }  

47.    }  

48.  

49.    @Test  

50.    public final void test() {  

51.  

52.        setUpExpectatioin();  

53.  

54.        setUpUserManagerWithMockAddressService();  

55.  

56.        invokeAndVerify();  

57.    }  

58.  

59.    /**  

60.     * 建立期望。

  

61.     * */  

62.    protected abstract void setUpExpectatioin();  

63.  

64.    /**  

65.     * 调用方法并且验证结果。

  

66.     * */  

67.    protected abstract void invokeAndVerify();  

68.}  

这样一来,我们以后的例子中只用关心setUpExpectatioin()和invokeAndVerify()方法就好了。

 

第2章期望 

好了,让我们来看看一个期望的框架。

Java代码  

1.invocation-count (mock-object).method(argument-constraints);  

2.    inSequence(sequence-name);  

3.    when(state-machine.is(state-name));  

4.    will(action);  

5.    then(state-machine.is(new-state-name));  

invocation-count调用的次数约束 

mock-objectmock对象 

method方法 

argument-constraints参数约束 

inSequence顺序 

when当mockery的状态为指定的时候触发。

 

will(action)方法触发的动作 

then方法触发后设置mockery的状态 

这个稍微复杂一些,一下子不明白是正常的,后面讲到其中的细节时,可以回来在看看这个框架。

 

第3章返回值 

调用一个方法,可以设置它的返回值。

即设置will(action)。

Java代码  

1.@Override  

2.protected void setUpExpectatioin() {  

3.    context.checking(new Expectations() {  

4.        {  

5.            // 当参数为"allen"的时候,addressServcie对象的findAddress方法返回一个Adress对象。

   

6.            allowing(addressServcie).findAddress("allen");  

7.            will(returnValue(Para.BeiJing));  

8.  

9.            // 当参数为null的时候,抛出IllegalArgumentException异常。

   

10.            allowing(addressServcie).findAddress(null);  

11.            will(throwException(new IllegalArgumentException()));  

12.        }  

13.    });  

14.}  

15.  

16.@Override  

17.protected void invokeAndVerify() {  

18.    assertFindAddress("allen", Result.BeiJing);  

19.    assertFindAddressFail(null);  

20.}  

这里演示了两种调用方法的结果,返回值和抛异常。

 

使用jmock可以返回常量值,也可以根据变量生成返回值。

 

抛异常是同样的,可以模拟在不同场景下抛的各种异常。

 

对于Iterator的返回值,jmock也提供了特殊支持。

Java代码  

1.@Override  

2.protected void setUpExpectatioin() {  

3.    // 生成地址列表   

4.    final List

 addresses = new ArrayList
();  

5.    addresses.add(Para.Xian);  

6.    addresses.add(Para.HangZhou);  

7.  

8.    final Iterator

 iterator = addresses.iterator();  

9.  

10.    // 设置期望。

   

11.    context.checking(new Expectations() {  

12.        {  

13.            // 当参数为"allen"的时候,addressServcie对象的findAddresses方法用returnvalue返回一个Iterator

对象。

   

14.            allowing(addressServcie).findAddresses("allen");  

15.            will(returnValue(iterator));  

16.  

17.            // 当参数为"dandan"的时候,addressServcie对象的findAddresses方法用returnIterator返回一个Iterator

对象。

   

18.            allowing(addressServcie).findAddresses("dandan");  

19.            will(returnIterator(addresses));  

20.        }  

21.    });  

22.  

23.}  

24.  

25.@Override  

26.protected void invokeAndVerify() {  

27.  

28.    Iterator

 resultIterator = null;  

29.  

30.    // 第1次以"allen"调用方法   

31.    resultIterator = manager.findAddresses("allen");  

32.    // 断言返回的对象。

   

33.    assertIterator(resultIterator);  

34.  

35.    // 第2次以"allen"调用方法,返回的与第一次一样的iterator结果对象,所以这里没有next了。

   

36.    resultIterator = manager.findAddresses("allen");  

37.    Assert.assertFalse(resultIterator.hasNext());  

38.  

39.    // 第1次以"dandan"调用方法   

40.    resultIterator = manager.findAddresses("dandan");  

41.    // 断言返回的对象。

   

42.    assertIterator(resultIterator);  

43.  

44.    // 第2次以"dandan"调用方法,返回的是一个全新的iterator。

   

45.    resultIterator = manager.findAddresses("dandan");  

46.    // 断言返回的对象。

   

47.    assertIterator(resultIterator);  

48.}  

49.  

50./** 断言resultIterator中有两个期望的Address */  

51.private void assertIterator(Iterator

 resultIterator) {  

52.    Address address = null;  

53.    // 断言返回的对象。

   

54.    address = resultIterator.next();  

55.    Assert.assertEquals(Result.Xian, address);  

56.    address = resultIterator.next();  

57.    Assert.assertEquals(Result.HangZhou, address);  

58.    // 没有Address了。

   

59.    Assert.assertFalse(resultIterator.hasNext());  

60.}  

从这个例子可以看到对于Iterator,returnValue和returnIterator的不同。

Java代码  

1.@Override  

2.protected void setUpExpectatioin() {  

3.    // 设置期望。

   

4.    context.checking(new Expectations() {  

5.        {  

6.            // 当参数为"allen"的时候,addressServcie对象的findAddress方法返回一个Adress对象。

   

7.            allowing(addressServcie).findAddress("allen");  

8.            will(new Action() {  

9.  

10.                @Override  

11.                public Object invoke(Invocation invocation)  

12.                        throws Throwable {  

13.                    return Para.Xian;  

14.                }  

15.  

16.                @Override  

17.                public void describeTo(Description description) {  

18.                }  

19.            });  

20.        }  

21.    });  

22.}  

23.  

24.@Override  

25.protected void invokeAndVerify() {  

26.    assertFindAddress("allen", Result.Xian);  

27.}  

其实这里要返回一个Action,该Action负责返回调用的返回值。

既然知道了这个道理,我们自然可以自定义Action来返回方法调用的结果。

 

而returnValue,returnIterator,throwException只不过是一些Expectations提供的一些static方法用来方便的构建不同的Action。

 

除了刚才介绍的 

ReturnValueAction直接返回结果 

ThrowAction抛出异常 

ReturnIteratorAction返回Iterator 

还有 

VoidAction 

ReturnEnumerationAction返回Enumeration 

DoAllAction所有的Action都执行,但是只返回最后一个Action的结果。

 

ActionSequence每次调用返回其Actions列表中的下一个Action的结果。

 

CustomAction一个抽象的Action,方便自定义Action。

 

举个例子来说明DoAllAction和ActionSequence的使用。

Java代码  

1.@Override  

2.protected void setUpExpectatioin() {  

3.    // 设置期望。

   

4.    context.check

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 能源化工

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1