Java JMockit中有没有从模拟方法调用原始方法的方法?
在我的mock类中,我在模拟方法foo()。对于一些测试用例,我希望foo()的模拟实现返回一个特殊值。对于其他测试用例,我想使用foo()的实际实现。我在mock类中定义了一个布尔值,这样我就可以在mock方法中确定是返回特殊值,还是使用“real”方法。问题是,我似乎不知道如何从模拟方法调用真正的方法 我发现可以在mock对象中定义一个名为“it”的特殊成员(对象类型为mock)。这允许您从模拟实现中引用真实类。因此,我的计划是,如果需要调用foo()的“真实”实现,mock方法将调用它。foo()。但是,这不起作用,因为调用它.foo()只会再次调用模拟版本,而不是真正的版本,因此我最终使用无限递归 有什么办法可以让它工作吗 编辑:代码示例可能更清楚,下面是我当前的模拟方法实现的样子:Java JMockit中有没有从模拟方法调用原始方法的方法?,java,mocking,jmockit,Java,Mocking,Jmockit,在我的mock类中,我在模拟方法foo()。对于一些测试用例,我希望foo()的模拟实现返回一个特殊值。对于其他测试用例,我想使用foo()的实际实现。我在mock类中定义了一个布尔值,这样我就可以在mock方法中确定是返回特殊值,还是使用“real”方法。问题是,我似乎不知道如何从模拟方法调用真正的方法 我发现可以在mock对象中定义一个名为“it”的特殊成员(对象类型为mock)。这允许您从模拟实现中引用真实类。因此,我的计划是,如果需要调用foo()的“真实”实现,mock方法将调用它。f
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()。但这不起作用-似乎您只能在安装/拆卸中执行此操作。。。当我尝试这样做时,我的模拟实现从未被调用
解决方案说明:
起初我认为给出的答案不起作用,但在进一步研究之后,问题似乎是我将JMockit“核心”方法与“注释”驱动的方法混合在一起了。显然,在使用注释时,您需要使用Mockit.setupmock,而不是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();
}
}
}
除了抛出一个模拟对象,您还可以对要测试的对象进行子类化,并重写应该返回特殊值的方法 例如:
RealClass toTest = new RealClass(){
public String foo(){
return "special value";
}
}
//use toTest in test
通过在您的测试中保留此定义,其他人也可以清楚地知道哪些方法正在被“模拟”。我认为您可以通过
@Mock
注释来实现这一点。从文档中可以看出,Mock类上的@Mock(reentrant=true)
应该可以做到这一点
看
例如,请看这里
不过我还没有测试过这一点。在较新版本的JMockit中,可以从实现中调用。看
公共类MyMockClass扩展了实体模型{
私有静态布尔fakeIt=false;
@嘲弄
公共类foo(调用inv){
if(fakeIt){
返回新的SomeClass(“fakevalue”);
}否则{
返回库存继续();
}
}
}
谢谢你的建议!不幸的是,我不能使用这种方法,因为我正在模拟的类实际上不是由测试用例直接创建的。它是由正在测试的对象创建的。我一定是遗漏了什么。从文档上看,这听起来很有希望,但我使用reentrent=true还是false似乎并不重要,我得到的行为和以前一样。文档还说“默认情况下,这样的调用是不允许的,因为它们会导致无限递归…”所以我很困惑。在进一步检查后,我发现了我缺少的东西:)我更新了JavaDoc链接并添加了一个示例链接+答案是1。链接已经断开,因为它已经超过6年了。我认为值得注意的是,这个答案只有在问题被回答时才有效。此后,在JMockit的最新版本中,JMockit API中就不推荐使用这种方法。Trevor Robinson给出的答案现在是最好的答案,依我看。这个答案只有在你使用JMockit的旧版本时才仍然有效。这个答案中的链接是一个断开的链接。JMockIt的新链接:()
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();
}
}
}