至于我收集了关于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
}
}
使用上述两种方法调用方法的实际实现有什么区别?
答案 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);
此时,isASpy
与nonSpy
不是同一个对象;它是一个记录交互并转发到a copy of the original object nonSpy
的对象 - 除非您使用doReturn
或doThrow
(等)将其删除,此时它会跳过调用原始方法并执行您的存根操作。
您可以想象 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 没有委托对传递的实例进行调用,而是实际创建了它的副本。因此,如果您保留真实实例并与之交互,请不要期望间谍知道这些交互及其对实际实例状态的影响。推论是,当间谍上的未被取消的方法被称为但上的不在真实实例上时,你不会看到任何效果在实例上。