7

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

我发现您可以在名为“it”的模拟对象中定义一个特殊成员(具有被模拟对象的类型)。这允许您从模拟实现中引用真实的类。所以,我的计划是,如果我需要调用 foo() 的“真实”实现,模拟方法将调用 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();
        }
    }
}
4

3 回答 3

12

在更新的 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();
        }
    }
}
于 2015-06-10T01:06:33.233 回答
8

我认为您可以使用@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 #可重入

虽然我没有测试过这个..

于 2008-12-11T04:14:55.413 回答
1

除了投入模拟对象之外,您还可以将要测试的对象子类化并覆盖应该返回特殊值的方法。

例如:

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

//use toTest in test

通过将此定义保留在您的测试中,其他人也很清楚哪些方法正在被“模拟”。

于 2008-12-10T20:07:27.363 回答