3 回答
![?](http://img1.sycdn.imooc.com/545865890001495702200220-100-100.jpg)
TA贡献2036条经验 获得超8个赞
你试图做的实际上不是这样做的方式。您应该只测试XmlToCsv该类,而不是该类使用的类(DocumentBuilderFactory, DocumentBuilder, Document, StreamSource, Transformer, Source, Result)。
现在有两种方法可以走:干净的代码方式,或脏测试的方式。
最好的解决方案是为您使用的类建立一个依赖框架:
public class XmlToCsv {
@Inject
DocumentBuilderFactory factory;
@Inject
StreamSource stylesource;
@Inject
TransformerFactory transformerFactory;
public void xmlToCsv(String sourceXlsFile, String sourceCsvFile, String sourceXmlFile) throws Exception {
//define the files
File stylesheet = new File(sourceXlsFile);
File xmlSource = new File(sourceXmlFile);
//create the DocumentBuilder to parse the XML file
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlSource);
//input the stylesheet to transform the XML to
StreamSource stylesource = new StreamSource(stylesheet);
Transformer transformer = transformerFactory.newInstance().newTransformer(stylesource);
//write a new output file using the stylesheet format
Source source = new DOMSource(document);
Result outputTarget = new StreamResult(new File(sourceCsvFile));
transformer.transform(source, outputTarget);
}
}
现在可以通过将模拟注入可注入字段来完成测试:
@RunWith(MockitoJUnitRunner.class)
public class XmlToCsvTest {
@Mock
DocumentBuilderFactory factory;
@Mock
StreamSource style source;
@Mock
TransformerFactory transformerFactory;
@InjectMocks
XmlToCsv sut; // System Under Test
@Test
public void testOk() throws Exception {
// Mocks
DocumentBuilder documentBuilder = Mockito.mock(DocumentBuilder.class);
Document document = Mockito.mock(Document.class);
// Now you control all objects created in the class and you can test if the right methods are called
// when-clauses
Mockito.when(factory.newDocumentBuilder).thenReturn(documentBuilder);
Mockito.when(documentBuilder.parse(any(File.class)).thenReturn(document);
// Add all when's here
// now call the class
sut.xmlToCsv("", "", "");
// now verify all calls
verify(factory, times(1)).newDocumentBuilder();
verify(documentBuilder, times(1)).parse(any(File.class));
// etc.
}
}
肮脏的方法是使用 PowerMockito。使用 PowerMockito,您可以覆盖现有类的新方法。这确实是最后的手段,我不推荐它,但是当您无法更改源代码时可以使用它。它看起来像这样:
@RunWith(PowerMockRunner.class)
@PrepareForTest({XmlToCsv.class, DocumentBuilderFactory.class})
public class XmlToCsvTest {
XmlToCsv sut;
@Test
public void testXmlToCsv() throws Exception {
DocumentBuilder documentBuilder = Mockito.mock(DocumentBuilder.class);
Document document = Mockito.mock(Document.class);
//when phase
PowerMockito.mockStatic(DocumentBuilderFactory.newInstance).thenReturn(documentBuilder);
Mockito.when(factory.newDocumentBuilder).thenReturn(documentBuilder);
Mockito.when(documentBuilder.parse(any(File.class)).thenReturn(document);
// now call the class
sut.xmlToCsv("", "", "");
//now verify
verify(documentBuilder, times(1)).parse(any(File.class));
}
}
如您所见,示例并不完整,但您会发现不同之处。
![?](http://img1.sycdn.imooc.com/54584c5e0001491102200220-100-100.jpg)
TA贡献1796条经验 获得超7个赞
要测试代码生成器,这是我发现的最佳方法:
准备一组具有相同 XSL的测试用例:对于每个测试用例,一个 XML 输入文件和一个预期的 CSV 输出文件。将输入文件放入一个目录,将预期的文件放入另一个目录,但为每对文件(
case1.xml
和case1.csv
)设置相同的名称。使用应该进行测试和比较的私有方法编写 JUnit 类,然后
@Test
为每个要测试的案例添加一个方法:
import java.io.File;
import org.apache.commons.io.FileUtils;
public class XmlToCsvTest
{
private final File inputDir=new File("my_input_xml_files");
private final File expectedDir=new File("my_expected_csv_files");
private final File generatedDir=new File("my_generated_files"); // This is just a working dir
private void xmlToCsv(String xslFile, String inputFileName)
{
try
{
File inputXmlFile=new File(this.inputDir, inputFileName + ".xml");
File outputCsvFile=new File(this.generatedDir, inputFileName + ".csv");
File expectedCsvFile=new File(this.expectedDir, inputFileName + ".csv");
xmlToCsv(xslFile, outputCsvFile.getAbsolutePath(), inputXmlFile.getAbsolutePath());
FileUtils.contentEquals(expectedCsvFile, outputCsvFile);
}
catch (Exception e)
{
fail(e.toString());
}
}
@Test
public void xmlToCsvWithCase1()
{
xmlToCsv("myFirst.xsl", "case1");
}
@Test
public void xmlToCsvWithEmptyFile()
{
xmlToCsv("myFirst.xsl", "empty");
}
@Test
public void xmlToCsvWithOneRow()
{
xmlToCsv("myFirst.xsl", "one-row");
}
...
}
一旦您掌握了这项技术,您就可以通过添加其他 XSL 及其自己的测试用例来增加测试的复杂性。
不要忘记将文件集作为资源添加到您的项目中,以成为源代码控制系统的一部分。
注意:此方法假定每个输出文件仅取决于输入文件的内容。如果生成器添加了一些独立的内容(如当前日期、当前用户等),则必须进行先前的预处理。
![?](http://img1.sycdn.imooc.com/54586431000103bb02200220-100-100.jpg)
TA贡献1752条经验 获得超4个赞
看起来您想要测试此方法的方式是验证写入sourceCsvFile
参数的文件的预期内容,您可以通过在调用方法后读取内容来实现。我认为您不需要对 Mockito 做任何事情——您的所有参数都是 String 对象,因此无需创建任何模拟。
添加回答
举报