2017-06-08 74 views
2

我試圖用JMockit模擬SAXParser.parse(...)方法。 (InputStream,DefaultHandler)方法簽名,但當我試圖嘲笑解析(InputSource,DefaultHandler)簽名時,JMockit從不會看到調用並拋出MissingInvocation異常。JMockit不符合記錄的期望

下面的例子顯示了兩個測試用例,一個嘲諷的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: [email protected] 
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和1.32 JMockit

回答

2

TL; DR

使用@Capturing annnotation而不是@Mocked一個在InputSource測試。

說明

您的問題是SAXParser.parse(InputSource, DefaultHandler)方法由SAXParserImpl覆蓋。當您使用@Mocked註釋時,您只嘲笑SAXParser類中的方法。

SAXParserFactory.newInstance().newSAXParser()返回SAXParserImpl,所以對於InputStream方法,因爲沒有覆蓋,這是不言而喻的嘲笑SAXParser.parse(InputStream, DefaultHandler)方法。

但是,對於InputSource方法,由於存在重寫,它會轉到未模擬的方法,因此缺少調用。

如果您要使用Capturing註釋,它會嘲諷一個接口/類及其所有子類/子實現,那麼您將不會缺少調用異常。

+1

確實。除了JMockit 1.32以外,由於過去的健壯性問題,許多來自非標準包的內部JRE類(如'com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl')被從'@ Capturing'中排除。但在JMockit 1.33中,將允許使用「com.sun.org」。這就是說,IMO嘲笑一個XML解析器是不必要的,也是最好的避免。 –

+0

我使用1.8,所以沒有注意到:P – Alfergon