在 Expectations 块中模拟私有方法会导致 "IllegalStateException: Missing invocation to mocked type at this point"

Mocking a private method in an Expectations block causes "IllegalStateException: Missing invocation to mocked type at this point"

我有一个使用 JMockit Expectations 块的 JUnit 测试:

@Tested
private MyTestedClass myTestedClass;

@Injectable
private MyOtherClass myOtherClass;

@Test
public void publicBooleanMethodTest() {

    new Expectations() {{
        invoke(myOtherClass, "privateMethod");
        result = true;
    }};

    myTestedClass.run(); // Calls myOtherClass.privateMethod();
} 

但是,这会导致以下错误:

java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter

如您所见,myClass 是通过 @Injectable 模拟的,所以我不确定为什么会发生错误。我还发现,如果我将 privateMethod() 的范围更改为 public,一切正常。

这是怎么回事,我该如何解决?它在 JMockit 1.22 中运行良好,但现在在 JMockit 1.23 及更高版本中失败。

JMockit 1.23 删除了对 Expectations 块中模拟私有方法的支持。来自 release notes:

Version 1.23 (Apr 24, 2016):

  • Dropped support for the mocking of private methods/constructors when using the Expectations API, to prevent misuse. If still needed, they can be mocked or stubbed out with the application of a MockUp<T>.

不幸的是,错误的错误消息目前被视为 "too costly too fix" by the development team. 因此,在 JMockit 1.28 中添加了更好的错误消息讨论。

错误日志说使用 MockUp<T> 作为替代。在这种情况下,代码如下:

@Tested
private MyTestedClass myTestedClass;

@Injectable
private MyOtherClass myOtherClass;

@Test
public void publicBooleanMethodTest() {
    // Partially mock myOtherClass
    new MockUp<MyOtherClass>(myOtherClass) {
        @Mock boolean privateBooleanMethod() {
            return true;
        }
    };

    myTestedClass.run(); // Calls myOtherClass.privateMethod();
}