我使用的是Mockito 1.9.0。我想在JUnit测试中模拟类的单个方法的行为,所以我有
final MyClass myClassSpy = Mockito.spy(myInstance);
Mockito.when(myClassSpy.method1()).thenReturn(myResults);
问题是,在第二行中,myClassSpy.method1()实际上被调用了,导致了一个异常。我使用模拟的唯一原因是,以后无论何时调用myClassSpy.method1(),都不会调用真正的方法,并且将返回myResults对象。
MyClass是一个接口,myInstance是它的实现。
我需要做什么来纠正这种间谍行为?
另一个可能导致间谍问题的场景是,当您测试spring bean(使用spring测试框架)或在测试期间探查对象的其他框架时。
例子
@Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
在上面的代码中,Spring和Mockito都将尝试代理您的MonitoringDocumentsRepository对象,但Spring将首先代理,这将导致findMonitoringDocuments方法的真正调用。如果我们在存储库对象上放置间谍之后调试代码,它将在调试器中看起来像这样:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
@SpyBean来拯救
如果改用@Autowired注释,我们使用@SpyBean注释,我们将解决上述问题,SpyBean注释也将注入存储库对象,但它将首先由Mockito代理,并在调试器中看起来像这样
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
下面是代码:
@SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
有点晚了,但以上的解决方案并不适合我,所以分享我的0.02美元
Mokcito版本:1.10.19
MyClass.java
private int handleAction(List<String> argList, String action)
Test.java
MyClass spy = PowerMockito.spy(new MyClass());
以下没有为我工作(实际的方法正在被调用):
1.
doReturn(0).when(spy , "handleAction", ListUtils.EMPTY_LIST, new String());
2.
doReturn(0).when(spy , "handleAction", any(), anyString());
3.
doReturn(0).when(spy , "handleAction", null, null);
以下工作:
doReturn(0).when(spy , "handleAction", any(List.class), anyString());
另一个可能导致间谍问题的场景是,当您测试spring bean(使用spring测试框架)或在测试期间探查对象的其他框架时。
例子
@Autowired
private MonitoringDocumentsRepository repository
void test(){
repository = Mockito.spy(repository)
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
在上面的代码中,Spring和Mockito都将尝试代理您的MonitoringDocumentsRepository对象,但Spring将首先代理,这将导致findMonitoringDocuments方法的真正调用。如果我们在存储库对象上放置间谍之后调试代码,它将在调试器中看起来像这样:
repository = MonitoringDocumentsRepository$$EnhancerBySpringCGLIB$$MockitoMock$
@SpyBean来拯救
如果改用@Autowired注释,我们使用@SpyBean注释,我们将解决上述问题,SpyBean注释也将注入存储库对象,但它将首先由Mockito代理,并在调试器中看起来像这样
repository = MonitoringDocumentsRepository$$MockitoMock$$EnhancerBySpringCGLIB$
下面是代码:
@SpyBean
private MonitoringDocumentsRepository repository
void test(){
Mockito.doReturn(docs1, docs2)
.when(repository).findMonitoringDocuments(Mockito.nullable(MonitoringDocumentSearchRequest.class));
}
我的情况与公认的答案不同。我试图模拟一个包私有方法的实例,该实例不在该包中
package common;
public class Animal {
void packageProtected();
}
package instances;
class Dog extends Animal { }
测试类
package common;
public abstract class AnimalTest<T extends Animal> {
@Before
setup(){
doNothing().when(getInstance()).packageProtected();
}
abstract T getInstance();
}
package instances;
class DogTest extends AnimalTest<Dog> {
Dog getInstance(){
return spy(new Dog());
}
@Test
public void myTest(){}
}
编译是正确的,但是当它试图设置测试时,它反而调用了真正的方法。
将方法声明为protected或public可以修复该问题,但这并不是一个干净的解决方案。