技术开发 频道

单元测试中的伪对象

    上面的代码段定义了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。

0
相关文章