gpt4 book ai didi

java - 在Java单元测试中,使用Mockito,如何模拟调用XML DocumentBuilder,使其不返回FileNotFoundException

转载 作者:行者123 更新时间:2023-12-02 09:38:31 25 4
gpt4 key购买 nike

我想对一个函数进行单元测试,该函数调用另一个从磁盘读取 XML 文件的私有(private)函数。在单元测试中,我不想依赖磁盘上的真实文件,而是想使用保存在字符串变量中的 XML。

我尝试模拟 DocumentBuilderDocumentBuilderFactory,但没有成功,因为 DocumentBuilder 仍然想从磁盘读取文件,因此在单元测试中给出 FileNotFoundException

我想避免使用 PowerMockito。

下面是一个简短的代码片段,我可以用它重现该问题。

正在测试的类:

public class XMLReader {

private void readXml() throws IOException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder;
try {
docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse("path/to/xml");
} catch (ParserConfigurationException | SAXException e) {}
}

public boolean functionForTest() throws IOException {
readXml();
return true;
}

}

这是我的测试类:

public class AppTest {

private static final String CLUSTER_CONF_XML = "<element></element>";

private static Document buildXmlFromString(String xml) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
return dBuilder.parse(new ByteArrayInputStream(xml.getBytes(Charset.defaultCharset())));
}

@org.junit.Test
public void testFunctionForTest() throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory documentBuilderFactory = Mockito.mock(DocumentBuilderFactory.class);
DocumentBuilder xmlDocumentBuilder = Mockito.mock(DocumentBuilder.class);

try {
Mockito.when(documentBuilderFactory.newDocumentBuilder()).thenReturn(xmlDocumentBuilder);
Document doc = buildXmlFromString(CLUSTER_CONF_XML);
Mockito.when(xmlDocumentBuilder.parse(Mockito.anyString())).thenReturn(doc);
} catch (IOException e) {}

XMLReader xmlReader = new XMLReader();
boolean result = xmlReader.functionForTest();
assertEquals(result, true);

}
}

运行测试时,我收到 FileNotFoundException ,而预期的行为会使用保存在测试中使用的 String 变量中的 XML 内容来模拟 XML,从而避免异常和测试用例通过.

预先感谢您的帮助。

最佳答案

您的问题非常简单:您的 XMLReader 实例正在从“真实”依赖项调用方法,而不是从您所做的模拟中调用方法。您忘记“注入(inject)模拟”。

我会建议一个简单(虽然不干净)的解决方案,但您应该考虑重新设计以实现可测试性:

  1. 重构您的 XMLReader,以便它接收 DocumentBuilder 的依赖项作为构造函数的参数。
  2. 此外,不要在 readXml() 方法上实例化新的 DocumentBuilder,而是使用通过构造函数注入(inject)的依赖项的引用。
  3. 最后,当您在测试用例上实例化 XMLReader 时,请使用注入(inject)我提到的依赖项的构造函数(使用您刚刚创建的模拟)。然后,每当从 readXml() 方法进行调用时,都会从模拟中调用它。

示例:

public class XMLReader {

private DocumentBuilder documentBuilder;

private void readXml() throws IOException {
try {
Document doc = docBuilder.parse("path/to/xml");
} catch (ParserConfigurationException | SAXException e) {}
}

public boolean functionForTest() throws IOException {
readXml();
return true;
}

public XMLReader(DocumentBuilder documentBuilder) {
this.documentBuilder = documentBuilder;
}
}

关于java - 在Java单元测试中,使用Mockito,如何模拟调用XML DocumentBuilder,使其不返回FileNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57298740/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com