我的类结构如下:
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
}
}
我如何防止在我的方法中调用super.doSomethingParent()?(我正在编写测试的方法)
4条答案
按热度按时间but5z9lq1#
这种类结构很难模拟和测试。如果可能的话,我建议改变这种结构,因为在某些情况下,一个很难模拟和测试的类结构同样很难扩展和维护。
因此,如果您可以将类结构更改为类似于:
然后,您可以轻松地使用DoSomethingProvider和DbConnector的模拟创建示例,瞧......
如果你不能改变你的类结构,你需要使用Mockito.spy而不是Mockito.mock来stub特定的方法调用,但是使用真正的对象。
注意:使用
super
关键字可以防止Mockito存根该方法调用。我不知道是否有一种方法可以存根对super的调用。如果可能的话(比如你没有覆盖你类中的父方法),就省略该关键字。xoefb8l82#
我遇到了类似的问题,所以我发现使用
spy()
可以帮助。这种方法对我很有效。
uemypmqf3#
我找到了另一种方法,结果证明对我的情况非常有用。
在我的例子中,我需要创建一个新的类来扩展另一个类,其中包括一个非常复杂的(遗留代码)
protected final
方法。由于这种复杂性,重构来使用组合是不可能的,所以下面是我的想法。假设我有以下内容:
下面是我重新排列代码的方法:
当为“生产”目的创建
MyNewClass
的示例时,我可以使用默认构造函数。然而,在编写单元测试时,我会使用构造函数,在这里我可以注入
ComplexStuffExecutor
,在那里提供一个模拟,并且只测试来自MyNewClass
的自定义逻辑,即:初看起来,似乎只是为了使代码可测试而添加了一些样板代码。然而,我也可以将其视为代码实际应该是什么样子的一个指标。也许有一天有人(他会找到勇气和预算;))可以重构代码,例如用来自
Parent
的doComplexStuff
的逻辑实现ComplexStuffExecutor
,将其注入到MyNewClass
中,并摆脱继承。hjqgdpho4#
以下是具体操作方法
来源:https://blog.jdriven.com/2013/05/mock-superclass-method-with-mockito/