mockitojava中的单元测试Mock继承方法
我的班级结构如下:
public class MyParentClass {
void doSomethingParent() {
System.out.println("something in parent");
}
}
public class MyClass extends MyParentClass {
protected String createDummyRequest(Holder myHolder) {
//...
super.doSomethingParent();//I want to avoid this
//...
callingDB();
return "processedOutput";
}
private void callingDB() {
System.out.println("Calling to DB");
}
}
然后我的单元测试:
public class UnitTest {
public void testCreateDummyRequest() {
//create my mock holder
Holder mockHolder = new Holder();
MyClass mockObj = Mockito.mock(MyClass.class);
//mock doSomethingParent()
//mock callingDB()
//as mockObj is a fully mock, but I need to run my real method
//Mockito.when(mockObj.createDummyRequest(mockHolder)).thenCallRealMethod();
mockObj.createDummyRequest(mockHolder);
//Problem: doSomethingParent() is getting called though I have mocked it
}
}
如何防止调用超级用户。doSomethingParent()在我的方法中?(我正在编写测试的方法)
# 1 楼答案
我也遇到了类似的问题,所以我发现使用
spy()
可以解决这个问题这种方法适合我
# 2 楼答案
我找到了另一种方法,这在我的案例中非常有用
在我的例子中,我需要创建一个扩展另一个类的新类,其中包括一个非常复杂的(遗留代码)
protected final
方法。由于复杂性,实际上不可能通过重构来使用组合,所以我想到了以下几点假设我有以下几点:
下面是我如何重新排列此代码的:
为“生产”目的创建
MyNewClass
实例时,我可以使用默认构造函数然而,在编写单元测试时,我会使用构造函数,在这里我可以注入
ComplexStuffExecutor
,在那里提供一个模拟,并且只从MyNewClass
测试我的自定义逻辑,即:乍一看,添加一些样板代码似乎只是为了使代码可测试。但是,我也可以将其视为代码实际外观的指示器。也许有一天某个人(他会找到勇气和预算;)可以重构代码,例如使用
doComplexStuff
中的逻辑和Parent
中的逻辑来实现ComplexStuffExecutor
,将其注入MyNewClass
并摆脱继承# 3 楼答案
使用这种类结构,模拟和测试是非常困难的。如果可能的话,我建议更改结构,因为在mist情况下,很难模拟和测试的类结构同样很难扩展和维护
因此,如果您可以将您的类结构更改为类似于:
然后,您可以轻松地使用DoSomethingProvider和DbConnector的模拟创建实例,瞧
如果不能更改类结构,则需要使用Mockito。间谍而不是莫基托。模拟特定于存根的方法调用,但使用真实对象
注意:使用
super
关键字可以防止Mockito中断该方法调用。我不知道是否有办法将呼叫存根到super。如果可能的话(就像您没有重写类中的父方法一样),只需ommit关键字即可