声明:
Author:赵志乾
Date:2017-7-30
Declaration:All Right Reserved!!!
1、自动创建Mock对象
如果我们定义一个字段来引用Mock对象,那么JMock便会自动地完成对象的实例化,从而减少一些样板式的代码书写,减轻开发人员的负担。当然,为了让JMock知道要实例化那个字段所引用的对象,需要使用@Mock进行注解。如下面实例所示:
@Mock MyClass objMock;
2、指定Expectations
Expectations在Mockery对象中进行定义(假设先前已经创建了Mockery对象并命名为context),并且其内容要求放在双重花括号内。如下所示:
public void testSomeAction() { ... set up ... context.checking(new Expectations() {{ ... expectations go here ... }}); ... code being tested ... ... assertions ... }
Expectations块可以包含任意数量的预期,每一个预期都有如下结构。
invocation-count (mock-object).method(argument-constraints); inSequence(sequence-name); when(state-machine.is(state-name)); will(action); then(state-machine.is(new-state-name));
最常用到的结构如下:
调用次数(Mock对象名).要调用的方法名(参数);will(被调后要执行的动作);
其中,除了调用次数和Mock对象名外,其他各子句都是可选的。下面的测试方法给出了示例:
@Test public void returnsCachedObjectWithinTimeout() { context.checking(new Expectations() {{ oneOf (clock).time(); will(returnValue(loadTime)); oneOf (clock).time(); will(returnValue(fetchTime)); allowing (reloadPolicy).shouldReload(loadTime, fetchTime); will(returnValue(false)); oneOf (loader).load(KEY); will(returnValue(VALUE)); }}); Object actualValueFromFirstLookup = cache.lookup(KEY); Object actualValueFromSecondLookup = cache.lookup(KEY); assertSame("should be loaded object", VALUE, actualValueFromFirstLookup); assertSame("should be cached object", VALUE, actualValueFromSecondLookup); }
一个测试方法中可以包含多个Expectations块,后面的Expectations块会追加到其前面的那个Expectations块之后,这在呈现形式上对Expectations进行了清晰的分类。比如上面的那个测试可以写成下面的样式。
@Test public void returnsCachedObjectWithinTimeout() { context.checking(new Expectations() {{ oneOf (clock).time(); will(returnValue(loadTime)); oneOf (loader).load(KEY); will(returnValue(VALUE)); }}); Object actualValueFromFirstLookup = cache.lookup(KEY); context.checking(new Expectations() {{ oneOf (clock).time(); will(returnValue(fetchTime)); allowing (reloadPolicy).shouldReload(loadTime, fetchTime); will(returnValue(false)); }}); Object actualValueFromSecondLookup = cache.lookup(KEY); assertSame("should be loaded object", VALUE, actualValueFromFirstLookup); assertSame("should be cached object", VALUE, actualValueFromSecondLookup); }
Expectations块也可以用函数进行封装,从而使简化测试方法代码的复杂度,如下例所示:
@Test public void returnsCachedObjectWithinTimeout() { initiallyLoads(VALUE); Object valueFromFirstLookup = cache.lookup(KEY); cacheHasNotExpired(); Object valueFromSecondLookup = cache.lookup(KEY); assertSame("should have returned cached object", valueFromFirstLookup, valueFromSecondLookup); } private void initiallyLoads(Object value) { context.checking(new Expectations() {{ oneOf (clock).time(); will(returnValue(loadTime)); oneOf (loader).load(KEY); will(returnValue(value)); }}); } private void cacheHasNotExpired() { context.checking(new Expectations() {{ oneOf (clock).time(); will(returnValue(fetchTime)); allowing (reloadPolicy).shouldReload(loadTime, fetchTime); will(returnValue(false)); }}); }
注:本博客中的实例代码均来自于JMock Cookbook。