java JMockit 中有没有办法从模拟方法调用原始方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/357121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way in JMockit to call the original method from a mocked method?
提问by Eric Asberry
In my mock class, I'm mocking method foo(). For some test cases, I want the mock implementation of foo() to return a special value. For other test cases, I want to use the real implementation of foo(). I have a boolean defined in my mock class so that I can determine in the mock method whether I want to return the special value, or use the "real" method. The problem is, I can't seem to figure out how to call the real method from the mocked method.
在我的模拟课中,我正在模拟方法 foo()。对于某些测试用例,我希望 foo() 的模拟实现返回一个特殊值。对于其他测试用例,我想使用 foo() 的真实实现。我在模拟类中定义了一个布尔值,以便我可以在模拟方法中确定是要返回特殊值,还是使用“真实”方法。问题是,我似乎无法弄清楚如何从模拟方法中调用真正的方法。
I found that you can define a special member within the mock object named "it" (with type of the object being mocked). This allows you to reference the real class from the mock implementation. So, my plan was, if I needed to invoke the "real" implementation of foo(), the mock method would call it.foo(). However, this doesn't work, because calling it.foo() just calls the mock version again, not the real version, so I end up with infinite recursion.
我发现您可以在名为“it”的模拟对象中定义一个特殊成员(带有被模拟对象的类型)。这允许您从模拟实现中引用真实的类。所以,我的计划是,如果我需要调用 foo() 的“真实”实现,模拟方法将调用 it.foo()。但是,这不起作用,因为调用 it.foo() 只是再次调用模拟版本,而不是真实版本,所以我最终会无限递归。
Is there some way to make this work?
有什么方法可以使这项工作?
EDIT: it might be clearer with a code example, here's what my current mocked method implementation looks like:
编辑:使用代码示例可能会更清楚,这是我当前的模拟方法实现的样子:
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();
}
}
EDIT 2: Also, for most of my test cases I do NOTwant the mock implementation. So my initial attempt at this was to only call Mockit.redefineMethods() within those test cases where I needed the mock object. But this didn't work - it seems you can only do this within setup/teardown ... my mock implementation never got called when I tried that.
编辑 2:另外,对于我的大多数测试用例,我不想要模拟实现。所以我最初的尝试是只在我需要模拟对象的那些测试用例中调用 Mockit.redefineMethods() 。但这不起作用 - 似乎您只能在设置/拆卸中执行此操作……当我尝试这样做时,我的模拟实现从未被调用。
NOTES ON SOLUTION:
解决方案说明:
At first I didn't think the answer given worked, but after playing with it some more, it seems the problem is that I was mixing JMockit "core" methods with the "annotation" driven methods. Apparently when using the annotation you need to use Mockit.setupMocks, not Mockit.redefineMethods(). This is what finally worked:
起初我不认为给出的答案有效,但是在玩了更多之后,问题似乎是我将 JMockit“核心”方法与“注释”驱动方法混合在一起。显然,在使用注释时,您需要使用 Mockit.setupMocks,而不是 Mockit.redefineMethods()。这是最终奏效的:
@Before
public void setUp() throws Exception
{
Mockit.setUpMocks(MyMockClass.class);
}
Then, for the mock 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();
}
}
}
回答by Trevor Robinson
In more recent versions of JMockit, Invocation.proceed()can be called from within a MockUpimplementation. See Faking: Proceeding into the real implementation.
在最新版本的 JMockit 中,Invocation.proceed()可以从MockUp实现中调用。请参阅伪造:进入真正的实现。
public class MyMockClass extends MockUp<RealClass> {
private static boolean fakeIt = false;
@Mock
public SomeClass foo(Invocation inv) {
if (fakeIt) {
return new SomeClass("fakevalue");
} else {
return inv.proceed();
}
}
}
回答by Kris Pruden
I think you can do this with the @Mockannotation. From the docs, @Mock(reentrant=true)on your mock class should do it.
我认为您可以使用@Mock注释来做到这一点。从文档中,@Mock(reentrant=true)在你的模拟课上应该这样做。
See http://jmockit.googlecode.com/svn/trunk/www/javadoc/mockit/Mock.html
For an example look here http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html#reentrant
请参阅http://jmockit.googlecode.com/svn/trunk/www/javadoc/mockit/Mock.html
例如,请参见此处http://jmockit.googlecode.com/svn/trunk/www/tutorial/StateBasedTesting.html #可重入
I haven't tested this though..
我还没有测试过这个。。
回答by ebo
Instead of throwing in a mock object you could also subclass the object you want to test and override the methods that should return special values.
除了抛出模拟对象之外,您还可以将要测试的对象子类化并覆盖应该返回特殊值的方法。
For example:
例如:
RealClass toTest = new RealClass(){
public String foo(){
return "special value";
}
}
//use toTest in test
By keeping this definition within your test it is also clear for others which methods are being 'mocked'.
通过在您的测试中保留此定义,其他人也可以清楚哪些方法正在被“模拟”。

