上面的代码段定义了bar(10)方法只能被调用一次。如果提供一个范围又会怎么样呢?
...
foo.bar(10);
//define the behavior -- return "ok" when the
//argument is 10. And this method is expected
//to be called at least once and at most 3
//times.
setReturnValue("ok", 1, 3);
...
现在bar(10)被限制至少被调用一次最多3次。更方便的是Range已经预定义了一些限制范围。
...
foo.bar(10);
//define the behavior -- return "ok" when the
//argument is 10. And this method is expected
//to be called at least once.
setReturnValue("ok", Range.ONE_OR_MORE);
...
Range.ONE_OR_MORE是一个预定义的Range实例,这意味着方法应该被调用至少一次。如果setReturnValue()中没有定义调用次数限制,如setReturnValue("Hello"),Range.ONE_OR_MORE被认为是缺省值。还有两个预定义的Range实例,Range.ONE(就一次)和Range.ZERO_OR_MORE(对调用次数没有限制)。
这儿还有一个特定的设置返回值的方法:setDefaultReturnValue()。他将代替方法的参数值作为返回值,缺省的调用次数限制为Range.ONE_OR_MORE。这被称为方法参数值敏感性。
...
foo.bar(10);
//define the behavior -- return "ok" when calling
//bar(int) despite the argument value.
setDefaultReturnValue("ok");
...
o setThrowable
setThrowable(Throwable throwable)被用来定义方法调用异常抛出的行为。如果给定的throwable不匹配方法的异常定义,则AssertionFailedError会被抛出。调用次数的限制与方法参数值敏感性是一致的。
...
try {
foo.dummy();
} catch (Exception e) {
//skip
}
//define the behavior -- throw ParseException
//when call dummy(). And this method is expected
//to be called exactly once.
control.setThrowable(new ParseException("", 0), 1);
...
o setVoidCallable()
setVoidCallable()被用于没有返回值的方法。调用次数的限制与方法参数值敏感性是一致的。
...
try {
foo.dummy();
} catch (Exception e) {
//skip
}
//define the behavior -- no return value
//when calling dummy(). And this method is expected
//to be called at least once.
control.setVoidCallable();
...
o Set ArgumentsMatcher
在工作态时,MockControl会在伪对象的方法被调用时搜索预定义的行为。有三个因素会影响搜索的标准:方法标识,参数值和调用次数限制。第一和第三个因素是固定的。第二个因素可以通过参数值敏感性来忽略。更灵活的是,还可以自定义参数值匹配规则。setMatcher()可以通过ArgumentsMatcher在准备态时使用。
public interface ArgumentsMatcher {
public boolean matches(Object[] expected,
Object[] actual);
}
ArgumentsMatcher唯一的方法matches()包含两个参数。一个是期望的参数值数组(如果参数值敏感特性应用时为NULL)。另一个是实际参数值数组。如果参数值匹配就返回真。
...
foo.isSame(null);
//set the argument match rule -- always match
//no matter what parameter is given
control.setMatcher(MockControl.ALWAYS_MATCHER);
//define the behavior -- return true when call
//isSame(). And this method is expected
//to be called at least once.
control.setReturnValue(true, 1);
...
MockControl中有三个预定义的ArgumentsMatcher实例。MockControl.ALWAYS_MATCHER在匹配时始终返回真而不管给什么参数值。MockControl.EQUALS_MATCHER会为参数值数组的每一个元素调用equals()方法。MockControl.ARRAY_MATCHER与MockControl.EQUALS_MATCHER基本一致,除了他调用的是Arrays.equals()。当然,开发人员可以实现自己的ArgumentsMatcher。
然而自定义的ArgumentsMatcher有一个副作用是需要定义方法调用的输出参数值。
...
//just to demonstrate the function
//of out parameter value definition
foo.add(new String[]{null, null});
//set the argument match rule -- always
//match no matter what parameter given.
//Also defined the value of out param.
control.setMatcher(new ArgumentsMatcher() {
public boolean matches(Object[] expected,
Object[] actual) {
((StringBuffer)actual[0])
.append(actual[1]);
return true;
}
});
//define the behavior of add().
//This method is expected to be called at
//least once.
control.setVoidCallable(true, 1);
...
setDefaultMatcher()设置MockControl的缺省ArgumentsMatcher实例。如果没有特定的ArgumentsMatcher,缺省的ArgumentsMatcher会被使用。这个方法应该在任何方法调用行为定义前被调用。否则,会抛出AssertionFailedError异常。
//get mock control
MockControl control = ...;
//get mock object
Foo foo = (Foo)control.getMock();
//set default ArgumentsMatcher
control.setDefaultMatcher(
MockControl.ALWAYS_MATCHER);
//begin behavior definition
foo.bar(10);
control.setReturnValue("ok");
...
如果没有使用setDefaultMatcher(),MockControl.ARRAY_MATCHER就是缺省的ArgumentsMatcher。