JMockit tidak sesuai dengan ekspektasi yang tercatat

Saya mencoba mengejek metode SAXParser.parse(...) menggunakan JMockit.

Saya berhasil mengatur Ekspektasi untuk tanda tangan metode parse(InputStream, DefaultHandler), tetapi ketika saya mencoba meniru tanda tangan parse(InputSource, DefaultHandler), JMockit tidak pernah melihat pemanggilan dan memunculkan pengecualian MissingInvocation.

Contoh berikut menunjukkan dua kasus pengujian, satu meniru ragam InputSource dan satu lagi meniru ragam 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());
    }
}

Menjalankan testcase menghasilkan:

    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

Seperti yang Anda lihat, versi InputSource gagal, sedangkan versi InputStream berfungsi seperti yang diharapkan.

Saya menggunakan Junit 4.12 dan JMockit 1.32


person eakst7    schedule 08.06.2017    source sumber


Jawaban (1)


TL;DR

Gunakan anotasi @Capturing alih-alih anotasi @Mocked pada pengujian InputSource.

Penjelasan

Masalah Anda adalah metode SAXParser.parse(InputSource, DefaultHandler) ditimpa oleh SAXParserImpl. Saat Anda menggunakan anotasi @Mocked, Anda hanya mengejek metode dari kelas SAXParser.

SAXParserFactory.newInstance().newSAXParser() mengembalikan SAXParserImpl, jadi untuk metode InputStream, karena tidak ada override, ia beralih ke metode SAXParser.parse(InputStream, DefaultHandler) yang diolok-olok.

TAPI, untuk metode InputSource, karena ada override, maka metode tersebut beralih ke metode yang tidak diolok-olok, dan karenanya pemanggilannya hilang.

Jika Anda menggunakan anotasi Capturing, yang mengolok-olok antarmuka/kelas dan semua sub-kelas/sub-implementasinya, Anda tidak akan memiliki pengecualian pemanggilan yang hilang.

person Alfergon    schedule 09.06.2017
comment
Memang. Kecuali hingga JMockit 1.32, banyak kelas JRE internal dari paket non-standar (seperti com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl) dikecualikan dari @Capturing karena masalah ketahanan di masa lalu. Namun, di JMockit 1.33, com.sun.org akan diizinkan. Oleh karena itu, IMO yang mengejek parser XML tidak diperlukan dan sebaiknya dihindari. - person Rogério; 10.06.2017
comment
Saya menggunakan 1.8 jadi tidak menyadarinya :P - person Alfergon; 12.06.2017