0

我在 JUnit/JMock 中遇到了某个错误。我试图模拟几个对象,然后断言所有期望都得到满足。我正在运行一个简单的测试,例如:

@Test
public void sellingPutOptionProductDoesNotCauseDisclosure() throws PositionVerificationException, DataLoadException, MissingPriceException {
    final OptionProduct optionProduct = setupOptionProduct();
    context.assertIsSatisfied();
}

private OptionProduct setupOptionProduct() {
    final Option optionProduct = context.mock(Option.class);
    context.checking(new Expectations() {
        {
            oneOf(optionProduct).getUnderlyingProduct();
            will(returnValue(new Object()));
        }
    });
    return optionProduct;
}

Option 是一个对象,我正在像这样使用 Mockery:

context = new Mockery() {
    {
        setImposteriser(ClassImposteriser.INSTANCE);
    }
};

如果我运行上述测试,我正在测试通过,JVM 不会终止并且控制台中的最后一个打印输出是:

线程“主”中的异常

任何想法可能导致这种情况?

4

1 回答 1

0

我参加聚会有点晚了,但我也遇到了类似的问题,并且能够找到原因。
通常,当调用不属于预期的方法时,JMock 会构建日志,告诉您预期的内容未找到。就我而言,它在遇到意外呼叫后尝试创建该日志消息。创建日志消息的行为引发了一个异常,这让 JMock 感到很困惑,它报告测试通过了,而实际上它却失败了。

就我而言,引发异常的原因是传递给“意外”函数调用的参数之一是类的实例。该类部分是用模拟对象初始化的。当 JMock 试图构建错误消息来告诉我意外调用时,它需要描述参数。通常它会说类似unexpected invocation: myobject.myMethod(param1,param2).

因为在我的例子中,param1 包含的成员变量是模拟对象,并且 param1 类没有定义 toString(),所以使用了默认的 Object.toString()。

Object.toString() 定义为:return getClass().getName() + "@" + Integer.toHexString(hashCode());

我的哈希码实现param1是使用其中一些模拟对象。那些对模拟对象计算哈希码的调用本身就是“意外”调用,导致 JMock 在尝试向我描述测试失败时抛出异常。

不幸的是,JMock 并没有认识到这种情况并仍然尽可能多地报告失败,而是似乎完全放弃并报告测试为通过并随便提及Exception in thread "main."

要查看这是否发生在您身上,我建议您检查有问题的函数调用中涉及的参数。如果它们中的任何一个是类,而不是接口,您应该查看它们对 equals / hashcode / toString 的使用是否使用了对成员变量的任何可疑调用,这些调用可能与您的场景被模拟的方式不匹配。

于 2013-05-30T21:46:24.500 回答