【问题标题】:How to use JUnit to test the result of SAX parser?如何使用 JUnit 测试 SAX 解析器的结果?
【发布时间】:2014-02-17 08:58:36
【问题描述】:

我创建了一个 XML 解析器来解析一些 xml 配置文件。解析器的结果在回调监听器中返回,如下所示:

interface OnParseResultListener {
    void onFinished(Result result);
}

而解析器通过传入xml文件路径和监听器来获取Result对象:

MyParser parser = new MyParser();
parser.parse("conf.xml", new OnParseResultListener(){
    void onFinished(Result result) {
        // get the Result object here
    }
});

现在我想编写 JUnit 代码来测试 MyParser 是否运行良好。但是当我把上面的代码放到一个测试方法中时,测试方法总是在onFinished()被调用之前就被终止了。

我尝试在调用parse() 之后使用wait(),并在解析完成时在onFinished() 中使用notify(),但它一直在等待。我的猜测是 JUnit 线程被阻塞了,但是 SAX XMLReader 需要向那个线程发送事件,所以它不会通过。

所以我不能阻塞 JUnit 线程,但它在我的解析完成之前就结束了。我可以做些什么来测试解析结果??

MyParser 大致如下:

public class MyParser {
    OnParserResultListener listener;
    public void parse(InputStream xml, OnParserResultListener listener) {
        this.listener = listener;
        SAXParserFactory factory = SAXParserFactory.newInstance();
        SAXParser parser;
        try {
            parser = factory.newSAXParser();
            XMLReader xmlReader = parser.getXMLReader();

            //handle xml parsing events in a customized BaseHandler
            xmlReader.setContentHandler(new BaseHandler());

            InputSource is = new InputSource(xml);
            xmlReader.parse(is);
        } catch (Exception e) {} 
    }
}

class BaseHandler extends DefaultHandler {
    public void startElement(String u, String l, String q, Attributes a) {
        .... //handle xml tag
    }

    public void endElement(String r, String l, String q) throws SAXException {
        .... //read xml value, save to a Result object

        //return the Result object via OnParserResultListener's callback method
        this.listener.onFinished(Result);
    }
    ....//other methods
}

【问题讨论】:

    标签: xml junit


    【解决方案1】:

    您需要在回调中使用锁定机制,以便在传递结果时暂停调用线程。

    您还希望在从未触发回调的情况下使测试超时。像下面这样的东西应该可以工作:

    @Test(timeout = 5000) 
    public void receivesResultsFromParser() {
        final Semaphore latch = new Semaphore(1);
        new Thread(new Runnable() {
           public void run() {
               MyParser parser = new MyParser(); 
               parser.parse("conf.xml", new OnParseResultListener(){
                   void onFinished(Result result) {
                       // do result validation here
                       latch.release();
                   }
               });
            }
         }).start();
    
         latch.acquire();
    }
    

    【讨论】:

    • 感谢@MrWiggles,但添加信号量并不能帮助解决这个问题。因为 Semaphore.acquire() 阻塞了 JUnit 线程,所以永远不会调用 onFinished() ,直到测试超时并终止。因为在 MyParser 中我使用 XMLReader 来解析 XML,所以我认为如果 JUnit 线程被阻塞,XMLReader 就会停止工作。
    • 我的错,我认为您的解析器在不同的线程中运行。采用上述方法并在单独的线程中执行解析器。信号量将确保文本然后等待完成。我已经更新了代码
    • 嗨@MrWiggles,使用线程有同样的问题。因为 MyParser.parse() 并没有阻塞线程,需要一定的时间才能完成解析,但是 run() 方法结束,线程在 MyParser.parse() 被调用后立即停止,所以 OnParseResultListener 的 onFinished() 永远不可能回调。
    • 把MyParser的代码分享给大家
    猜你喜欢
    • 2013-02-05
    • 1970-01-01
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 2011-12-03
    • 1970-01-01
    • 2012-08-27
    • 1970-01-01
    相关资源
    最近更新 更多