Mockito:如何模拟XML Document对象以从XPath中检索值

时间:2015-03-11 11:19:21

标签: java xml xpath mockito

我正在尝试模拟一个org.w3c.dom.Document对象,这样调用XPath.evaluate()应该返回一个定义的值,例如foo,如下所示:

Document doc = Mockito.mock(Document.class);    
Mockito.when(XPathUtils.xpath.evaluate("/MyNode/text()", doc, XPathConstants.STRING)).thenReturn("foo");

我将doc对象传递给目标方法,该方法将节点 MyNode 的文本内容提取为 foo

我尝试过模拟节点并在doc对象中设置如下:

            Node nodeMock = mock(Node.class);
            NodeList list = Mockito.mock(NodeList.class);
            Element element = Mockito.mock(Element.class);
            Mockito.when(list.getLength()).thenReturn(1);
            Mockito.when(list.item(0)).thenReturn(nodeMock);
            Mockito.when(doc.getNodeType()).thenReturn(Node.DOCUMENT_NODE);
            Mockito.when(element.getNodeType()).thenReturn(Node.ELEMENT_NODE);
            Mockito.when(nodeMock.getNodeType()).thenReturn(Node.TEXT_NODE);
            Mockito.when(doc.hasChildNodes()).thenReturn(false);
            Mockito.when(element.hasChildNodes()).thenReturn(true);
            Mockito.when(nodeMock.hasChildNodes()).thenReturn(false);
            Mockito.when(nodeMock.getNodeName()).thenReturn("MyNode");
            Mockito.when(nodeMock.getTextContent()).thenReturn("MyValue");
            Mockito.when(element.getChildNodes()).thenReturn(list);
            Mockito.when(doc.getDocumentElement()).thenReturn(element);

但这会产生如下错误:

  

org.mockito.exceptions.misusing.WrongTypeOfReturnValue:String不能   由hasChildNodes()返回hasChildNodes()应返回boolean

我的方法是否正确,我只是缺少另一个模拟,或者我应该采用不同的方法?请帮忙。

2 个答案:

答案 0 :(得分:3)

Don't mock types you don't own !,这是错误的。

为了避免重复,这里的答案解释了为什么https://stackoverflow.com/a/28698223/48136

编辑:我的意思是代码应该有可用的构建器方法(在生产或测试类路径中)应该能够创建<强>真实 Document无论该文档的来源是什么,但肯定不是模拟。

例如,这个工厂方法或构建器可以这样使用DocumentBuilder

class FakeXMLBuilder {

    static Document fromString(String xml) {
        DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
        return dBuilder.parse(new ByteArrayInputStream(xml.getBytes("UTF_8")));
    }
}

当然,这必须根据项目的需要量身定制,这可以进行更多定制。在我目前的项目中,我们有很多可以创建对象,json等的测试构建器。例如:

Leg leg      = legWithRandomId().contact("Bob").duration(234, SECONDS).build();
String leg   = legWithRandomId().contact("Bob").duration(234, SECONDS).toJSON();
String leg   = legWithRandomId().contact("Bob").duration(234, SECONDS).toXML();
Whatever leg = legWithRandomId().contact("Bob").duration(234, SECONDS).to(WhateverFactory.whateverFactory());

答案 1 :(得分:0)

Jsoup.parse()与测试XML字符串一起使用。像下面这样的东西应该可以工作,用于测试我假设为testClassInstance.readFromConnection(String url)的某些实例方法:

// Turn a block of XML (static String or one read from a file) into a Document
Document document = Jsoup.parse(articleXml);

// Tell Mockito what to do with the Document
Mockito.when(testClassInstance.readFromConnection(Mockito.any()))
  .thenReturn(document);

我习惯将其称为“模拟”文档,但是它只是创建并使用一个真实的文档,然后将其用于模拟其他方法。您可以根据自己的喜好构建document的xml版本,也可以使用其常规的setter对其进行操作,以测试代码对文件的作用。您还可以用一个常量字符串来代替读取文件的麻烦,只要它足够短以至于易于管理。