JMockit 不符合记录的期望
JMockit not matching recorded expectation
我正在尝试使用 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.<init>(SAXTest.java:20)
at SAXTest.testParseInputSource(SAXTest.java:19)
FAILURES!!!
Tests run: 2, Failures: 1
如您所见,InputSource 版本失败,而 InputStream 版本按预期工作。
我正在使用 Junit 4.12 和 JMockit 1.32
TL;DR
在 InputSource
测试中使用 @Capturing
注释而不是 @Mocked
注释。
说明
您的问题是 SAXParser.parse(InputSource, DefaultHandler)
方法被 SAXParserImpl
覆盖。当您使用 @Mocked
注释时,您只是在模拟 SAXParser
class.
中的方法
SAXParserFactory.newInstance().newSAXParser()
returns a SAXParserImpl
,所以对于 InputStream
方法,由于没有覆盖,它会转到模拟的 SAXParser.parse(InputStream, DefaultHandler)
方法。
但是,对于 InputSource
方法,由于有一个覆盖,它会转到未模拟的方法,因此缺少调用。
如果您要使用 Capturing
注释,它会模拟一个 interface/class 及其所有 sub-classes/sub-implementations,您将不会遇到缺少的调用异常。
我正在尝试使用 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.<init>(SAXTest.java:20)
at SAXTest.testParseInputSource(SAXTest.java:19)
FAILURES!!!
Tests run: 2, Failures: 1
如您所见,InputSource 版本失败,而 InputStream 版本按预期工作。
我正在使用 Junit 4.12 和 JMockit 1.32
TL;DR
在 InputSource
测试中使用 @Capturing
注释而不是 @Mocked
注释。
说明
您的问题是 SAXParser.parse(InputSource, DefaultHandler)
方法被 SAXParserImpl
覆盖。当您使用 @Mocked
注释时,您只是在模拟 SAXParser
class.
SAXParserFactory.newInstance().newSAXParser()
returns a SAXParserImpl
,所以对于 InputStream
方法,由于没有覆盖,它会转到模拟的 SAXParser.parse(InputStream, DefaultHandler)
方法。
但是,对于 InputSource
方法,由于有一个覆盖,它会转到未模拟的方法,因此缺少调用。
如果您要使用 Capturing
注释,它会模拟一个 interface/class 及其所有 sub-classes/sub-implementations,您将不会遇到缺少的调用异常。