当前位置: 首页 > 工具软件 > jMock > 使用案例 >

JMock实践---(一)定义Expectations

轩辕翰
2023-12-01

声明:

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。




 类似资料: