间谍和直接对象之间的区别

时间:2014-04-17 18:04:51

标签: java testing mockito

至于我收集了关于Mockito的知识,当我们窥探一个对象并调用任何方法时,就会执行它的实际实现。

class Abc {
    public int fun() {
         //to do stuff
         return 5;
    }
}

使用间谍测试:

Class AbcTest {
    public void testFun()
    {
        Abc ob= spy(Abc.class);
        ob.fun();   //calls real implementation
        //Other stuff
    }
}

没有间谍的测试:

Class AbcTest
{
    public void testFun() {
         Abc ob=new Abc();
         ob.fun();
         //other stuff
    }
}  

使用上述两种方法调用方法的实际实现有什么区别?

2 个答案:

答案 0 :(得分:2)

使用间谍应该会在被测系统中产生相同的行为,但如果您愿意,可以覆盖和验证方法行为。

class AbcTest {
  public void testFun()
  {
    Abc ob= spy(Abc.class);
    ob.fun();   //calls real implementation
    //Other stuff
  }
}

这(引自你的问题)不会这样编译;您需要spy(new Abc())而不是spy(Abc.class)。这是一个微妙的观点,但知道发生了什么事实上非常重要。


考虑一下:

Abc nonSpy = new Abc();
Abc isASpy = Mockito.spy(nonSpy);

此时,isASpynonSpy不是同一个对象;它是一个记录交互并转发到a copy of the original object nonSpy的对象 - 除非您使用doReturndoThrow(等)将其删除,此时它会跳过调用原始方法并执行您的存根操作。

您可以想象 Mockito为您编写了以下实现:

class AbcSpy extends Abc {             // simplified analogy of Mockito proxy
  @Override public void fun() {
    recordCallToFun();                 // record for verification later
    if (hasStubbedBehaviorForFun) {
      performStubbedBehaviorForFun();  // perform doReturn/doThrow/etc
      return;
    }
    copyOfOriginalObject.fun();        // call real method
  }
}

通过将isASpy传递给您正在测试的系统(而不是nonSpy),您可以为正在测试的系统提供一个与之交互的真实对象,并提供少数行为覆盖。当然,您也可以使用间谍简单地验证被测系统是否与合作者Abc正确交互。

答案 1 :(得分:-1)

@Spy或spy()方法可用于包装真实对象。除非另有说明,否则每次调用都会委托给该对象。

有时使用Mockito.when(对象)来捣乱间谍是不可能或不切实际的。因此对于间谍,建议始终使用doReturn | Answer | Throw()| CallRealMethod系列方法进行存根。例如:

List list = new LinkedList();
List spy = spy(list);

//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");

//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);

Mockito 没有委托对传递的实例进行调用,而是实际创建了它的副本。因此,如果您保留真实实例并与之交互,请不要期望间谍知道这些交互及其对实际实例状态的影响。推论是,当间谍上的未被取消的方法被称为上的不在真实实例上时,你不会看到任何效果在实例上。