如何模拟超级引用(超类)?

有时当我编写unit testing时,我应该模拟对超类的引用。

我读过这个问题: 问题

这个答案回答DI建议重构代码。 但我不能

如果超类方法足够大,这个答案另一个答案是不合适的。 在我的情况下,我有非常大的代码。 是的我知道它是SOLID OOD原则,但我应该写测试。 我没有足够的时间进行重构。

4年前问了这个问题!

目前Mockito或Powermock可以解决此问题吗?

更新

代码示例:

class BaseService { public void save() { // a lot of code here! I cannot change this code. } } public Childservice extends BaseService { public void save(){ //logic for testing super.save(); //logic for testing } } 

更新2

 public class Parent { public int save() { return 99; } } public class Child extends Parent { public int save() { int i = super.save(); return i*2; } } 

并测试:

 @RunWith(PowerMockRunner.class) @PrepareForTest(Parent.class) public class ParentTest { @Test public void testSave() { PowerMockito.suppress(PowerMockito.methodsDeclaredIn(Parent.class)); System.out.println(new Child().save()); } } 

输出:198

使用Powermock,您可以替换或抑制方法,因此可以更改BaseService.save()完成的操作。 您也可以使方法无法抑制。 您甚至可以抑制静态初始化程序块。

请阅读Powermock作者的博客文章 。 请参阅“更换”一章。

更新:

抑制似乎对我有用,但不是替换。 见下图: 在此处输入图像描述

与JMOCKIT

我已经尝试过使用JMockit,它可以模拟超级方法调用。 请看我的代码:

 public class Bar { public void bar() { System.out.println("Bar#bar()"); } } public class Foo extends Bar { public void bar() { super.bar(); System.out.println("Foo#bar()"); } } public final class MockBar extends MockUp { private boolean barCalled = false; @Mock public void bar() { barCalled = true; System.out.println("mocked bar"); } public boolean isBarCalled() { return barCalled; } public void setBarCalled(boolean barCalled) { this.barCalled = barCalled; } } public class FooTest { @Test public void barShouldCallSuperBar() { MockBar mockBar = new MockBar(); Foo foo = new Foo(); foo.bar(); } } 

控制台的结果是:

mocked bar Foo#bar()

与MOCKITO和POWERMOCKITO

 public class Bar { public void bar() { System.out.println("Bar#bar()"); } public int numBar() { System.out.println("Bar#numBar()"); return 99; } } public class Foo extends Bar { public void bar() { super.bar(); System.out.println("Foo#bar()"); } public int numBar() { System.out.println("Foo#numBar() - before-call super.numBar()"); int result = super.numBar(); System.out.println("Foo#numBar() - after-call super.numBar();"); return result; } } @RunWith(PowerMockRunner.class) @PrepareForTest(Bar.class) public class FooTest { @Test public void testBar() throws Exception { Method method = PowerMockito.method(Bar.class, "bar"); PowerMockito.suppress(method); Foo foo = new Foo(); foo.bar(); } @Test public void testNumBar() throws Exception { Method methodFoo = PowerMockito.method(Foo.class, "numBar"); PowerMockito.replace(methodFoo).with(new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return 1; } }); Foo foo = new Foo(); int numBar = foo.numBar(); Assert.assertEquals(1, numBar); } } 

testNumber()的结果是:

Foo#numBar() - before-call super.numBar() Foo#numBar() - after-call super.numBar();

您可以看到,没有调用bar#numBar,期望结果为1。

这是不可能的; 超类的全部意义在于它封装了上游状态和function,并且类层次结构基于extends关系在子类中进行了硬编码。