【发布时间】:2018-01-24 21:11:23
【问题描述】:
我一直在尝试编写一个单元测试,试图全面覆盖我的测试类。
我正在尝试测试它是否正确捕获了DOMUtil 类中此方法抛出的TransformerException:
public final class DOMUtil
{
// This class is entirely static, so there's no need to ever create an instance.
private DOMUtil()
{
// Do nothing.
}
...
...
/**
* Returns a String containing XML corresponding to a Document. The String
* consists of lines, indented to match the Document structure.
* @param doc - Document to be converted.
* @return String containing XML or null if an error occurs.
*/
public static String documentToString(final Document doc)
{
try
{
// Note that there is no control over many aspects of the conversion,
// e.g., insignificant whitespace, types of quotes.
final Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
tf.setOutputProperty(OutputKeys.INDENT, "yes");
final Writer out = new StringWriter();
tf.transform(new DOMSource(doc), new StreamResult(out));
return out.toString();
}
catch (final TransformerException e)
{
LOG.error("Error converting Document to String: " + e.getMessage());
return null;
}
}
}
我的 DOMUtilTest 类:
@RunWith(PowerMockRunner.class)
...
...
@PrepareForTest({Document.class, TransformerFactory.class, Transformer.class, DOMUtil.class, DocumentBuilder.class, DocumentBuilderFactory.class})
public class DOMUtilTest
{
/**
* Test documentToString with TransformerException
*/
@Test(expected=TransformerException.class)
public void testDocumentToStringTransformerException()
{
try
{
// Mocking Stuff
TransformerFactory fac = PowerMockito.mock(TransformerFactory.class);
Transformer transformer = PowerMockito.mock(Transformer.class);
// probably only need two of these??
PowerMockito.whenNew(TransformerFactory.class).withNoArguments().thenReturn(fac);
PowerMockito.whenNew(Transformer.class).withNoArguments().thenReturn(transformer);
PowerMockito.when(fac.newTransformer(ArgumentMatchers.any(Source.class))).thenReturn(transformer);
PowerMockito.when(fac.newTransformer()).thenReturn(transformer);
// spy in results
PowerMockito.spy(transformer);
PowerMockito.when(transformer, "transform", ArgumentMatchers.any(Source.class), ArgumentMatchers.any(Result.class)).thenThrow(new TransformerException("Mocked TransformerException"));
final String result = DOMUtil.documentToString(doc);
LOG.info("result length: " + result.length());
}
catch(Exception e)
{
LOG.error("Exception in testDocumentToStringTransformerException: " + e.getMessage());
fail("Exception in testDocumentToStringTransformerException: " + e.getMessage());
}
}
}
我觉得我已经尝试了所有可能的解决方案。我在其他类/方法上有很多类似条件的工作测试。我试过了
- 注解风格模拟/注入
- 间谍
- ArgumentMatchers.any(DOMSource.class)、ArgumentMatchers.any(StreamResult.class)(这会给出错误:来自 ArgumentMatchers 类型的方法 any(Class) 引用了缺少的类型 DOMSource)
以及我能想到的所有其他可能的方式。现在结果仍然显示:结果长度:25706(文档对象的实际长度)在复制文档之前没有出现异常。
这里是来自Java 7 API - Exceptions and Error Reporting的TransformationException的进一步解释。
TransformerException 是一般的异常,发生在 转型的过程。变压器异常可能会包装另一个 异常,如果有任何 TransformerException.printStackTrace() 方法被调用,它会产生一个堆栈转储列表, 从最近的开始。变压器例外还提供 一个 SourceLocator 对象,它指示源树中的位置或 转换说明发生错误。 可以调用 TransformerException.getMessageAndLocation() 来获取 带有位置信息的错误消息,以及 可以调用 TransformerException.getLocationAsString() 来获取 位置字符串。
我的假设是问题出在嘲笑这条线:
final Transformer tf = TransformerFactory.newInstance().newTransformer();
有没有人遇到过这样的情况,使用 JUnit 和 PowerMockito?
如果有人能指出我正确的方向或告诉我如何解决这个问题,任何帮助将不胜感激。
谢谢!
【问题讨论】:
-
正确的解决方案,IMO,将传递一个无效的
Document,它会以某种方式触发TransformerException。并且如果不能创建这样的无效文档,那么catch 块在实践中可能是无法访问的,不需要进行测试。
标签: java unit-testing testing junit mocking