在JMockit中是否有一种方法可以从模拟方法中调用原始方法?

在我的模拟类中,我正在模拟方法foo()。 对于某些测试用例,我希望foo()的模拟实现返回一个特殊值。 对于其他测试用例,我想使用foo()的实际实现。 我在我的mock类中定义了一个布尔值,以便我可以在mock方法中确定是否要返回特殊值,或使用“real”方法。 问题是,我似乎无法弄清楚如何从模拟方法调用真正的方法。

我发现你可以在名为“it”的模拟对象中定义一个特殊成员(具有被模拟对象的类型)。 这允许您从模拟实现中引用真实类。 所以,我的计划是,如果我需要调用foo()的“真实”实现,mock方法将调用it.foo()。 但是,这不起作用,因为调用it.foo()只是再次调用模拟版本,而不是真实版本,所以我最终得到无限递归。

有没有办法让这项工作?

编辑:使用代码示例可能更清楚,这是我当前的模拟方法实现的样子:

private RealClass it; ... public SomeClass foo() { if(fakeIt) { return new SomeClass("fakevalue"); } else { // doesn't work, just keeps calling the mock foo // in infinite recursion return it.foo(); } } 

编辑2:此外,对于我的大多数测试用例,我想要模拟实现。 所以我最初的尝试是在我需要模拟对象的那些测试用例中只调用Mockit.redefineMethods()。 但这不起作用 – 似乎你只能在setup / teardown中这样做…我的模拟实现从未在我尝试时被调用。

解决方案说明:

起初我并不认为给出的答案有效,但在使用它之后,似乎问题在于我将JMockit“核心”方法与“注释”驱动方法混合在一起。 显然,在使用注释时,您需要使用Mockit.setupMocks,而不是Mockit.redefineMethods()。 这是最终奏效的:

 @Before public void setUp() throws Exception { Mockit.setUpMocks(MyMockClass.class); } 

然后,对于模拟类:

 @MockClass(realClass = RealClass.class) public static class MyMockClass { private static boolean fakeIt = false; private RealClass it; @Mock(reentrant = true) public SomeClass foo() { if(fakeIt) { return new SomeClass("fakevalue"); } else { return it.foo(); } } } 

我想你可以用@Mock注释做到这一点。 从文档中,模拟类上的@Mock(reentrant=true)应该这样做。

见http://jmockit.googlecode.com/svn/trunk/www/javadoc/mockit/Mock.html
有关示例,请访问http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html#reentrant

我没有测试过这个..

在更新版本的JMockit中,可以从MockUp实现中Invocation.proceed() 。 请参阅伪造:继续进行实际实施 。

 public class MyMockClass extends MockUp { private static boolean fakeIt = false; @Mock public SomeClass foo(Invocation inv) { if (fakeIt) { return new SomeClass("fakevalue"); } else { return inv.proceed(); } } } 

您也可以将要测试的对象子类化,并覆盖应返回特殊值的方法,而不是抛出模拟对象。

例如:

 RealClass toTest = new RealClass(){ public String foo(){ return "special value"; } } //use toTest in test 

通过将此定义保留在您的测试中,对其他人来说,哪些方法被“嘲笑”也很清楚。