【问题标题】:JMockit not matching recorded expectationJMockit 不符合记录的期望
【发布时间】:2017-06-08 14:10:01
【问题描述】:

我正在尝试使用 JMockit 模拟 SAXParser.parse(...) 方法。

我能够成功地为 parse(InputStream, DefaultHandler) 方法签名设置 Expectations,但是当我尝试模拟 parse(InputSource, DefaultHandler) 签名时,JMockit 永远不会看到调用并抛出 MissingInvocation 异常。

以下示例显示了两个测试用例,一个模拟 InputSource 风格,一个模拟 InputStream 风格:

public class SAXTest {

    @Test(expected=RuntimeException.class)
    public void testParseInputSource(@Mocked final SAXParser saxParser) throws Exception {
        new Expectations() {{
            saxParser.parse((InputSource) any, (DefaultHandler) any); result = new RuntimeException("Fail now");
        }};

        SAXParser p = SAXParserFactory.newInstance().newSAXParser();
        InputSource isource = new InputSource(new StringReader("<test/>"));
        p.parse(isource, new DefaultHandler());    
    }

    @Test(expected=RuntimeException.class)
    public void testParseInputStream(@Mocked final SAXParser saxParser) throws Exception {
        new Expectations() {{
            saxParser.parse((InputStream) any, (DefaultHandler) any); result = new RuntimeException("Fail now");
        }};

        SAXParser p = SAXParserFactory.newInstance().newSAXParser();
        InputStream istream = new ByteArrayInputStream("</test>".getBytes());
        p.parse(istream, new DefaultHandler());
    }
}

运行测试用例结果:

    JUnit version 4.12
E.
Time: 0.069
There was 1 failure:
1) testParseInputSource(SAXTest)
java.lang.Exception: Unexpected exception, expected<java.lang.RuntimeException> but was<mockit.internal.MissingInvocation>
        at org.junit.internal.runners.statements.ExpectException.evaluate(ExpectException.java:28)
 ...
Caused by: Missing 1 invocation to:
javax.xml.parsers.SAXParser#parse(any org.xml.sax.InputSource, any org.xml.sax.helpers.DefaultHandler)
   on mock instance: $Subclass_SAXParser_param0@490d6c15
Caused by: Missing invocations
        at javax.xml.parsers.SAXParser.parse(SAXParser.java)
        at SAXTest$1.<init>(SAXTest.java:20)
        at SAXTest.testParseInputSource(SAXTest.java:19)

FAILURES!!!
Tests run: 2,  Failures: 1

如您所见,InputSource 版本失败,而 InputStream 版本按预期工作。

我正在使用 Junit 4.12 和 JMockit 1.32

【问题讨论】:

    标签: java jmockit


    【解决方案1】:

    TL;DR

    InputSource 测试中使用@Capturing 注释而不是@Mocked 注释。

    说明

    您的问题是SAXParser.parse(InputSource, DefaultHandler) 方法被SAXParserImpl 覆盖。当您使用 @Mocked 注释时,您只是在模拟来自 SAXParser 类的方法。

    SAXParserFactory.newInstance().newSAXParser() 返回一个SAXParserImpl,因此对于InputStream 方法,由于没有覆盖,它会转到模拟的SAXParser.parse(InputStream, DefaultHandler) 方法。

    但是,对于 InputSource 方法,由于存在覆盖,它会转到未模拟的方法,因此会丢失调用。

    如果您要使用模拟接口/类及其所有子类/子实现的Capturing 注释,则不会出现缺少调用异常。

    【讨论】:

    • 确实如此。除了到 JMockit 1.32 之外,由于过去的健壮性问题,许多来自非标准包的内部 JRE 类(例如com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl)被排除在@Capturing 之外。不过,在 JMockit 1.33 中,com.sun.org 将被允许。这就是说,IMO 模拟 XML 解析器是不必要的,最好避免。
    • 我使用的是 1.8,所以没注意到 :P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多