I have been trying to write a unit test in an attempt to reach full coverage on my class under test.
I am trying to test that it properly catches the TransformerException thrown from this method in class DOMUtil:
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;
}
}
}
My DOMUtilTest class:
@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());
}
}
}
I feel like I have tried every possible solution. I have a lot of working tests with similar conditions on other classes/methods. I have tried
and every other possible way I could think of. Right now the result is still showing: result length: 25706 (the real length of the doc object) without getting an exception before copying the document.
Here is a further explanation of TransformationException from Java 7 API - Exceptions and Error Reporting .
TransformerException is a general exception that occurs during the course of a transformation. A transformer exception may wrap another exception, and if any of the TransformerException.printStackTrace() methods are called on it, it will produce a list of stack dumps, starting from the most recent. The transformer exception also provides a SourceLocator object which indicates where in the source tree or transformation instructions the error occurred. TransformerException.getMessageAndLocation() may be called to get an error message with location info, and TransformerException.getLocationAsString() may be called to get just the location string.
My assumption is the problem is with mocking of the line:
final Transformer tf = TransformerFactory.newInstance().newTransformer();
Has anybody encountered a situation like this, with JUnit and PowerMockito?
If anybody could point me in the right direction or show me how to solve this any help would be greatly appreciated.
Thanks!
In theory this does not seem like the prettiest way of mocking the TransformerException , but upon a lot of research and attempts, I came up with the solution of mocking the Result outputTarget argument of tf.transform :
@Test
public void testDocumentToStringTransformerException() throws Exception
{
// Mocking Stuff
PowerMockito.whenNew(StringWriter.class).withNoArguments().thenReturn(null);
// Execute Method Under Test
final String result = DOMUtil.documentToString(doc);
// Verify Result
assertNull(result);
}
Which will ultimately give:
XML-22122: (Fatal Error) Invalid StreamResult - OutputStream, Writer, and SystemId are null.
encapsulated into a TransformerException. This allows me to test the TransformerException branches of code coverage.
So the good news is it is possible with mocking, instead of trying to figure out how to manipulate a Document object to throw the exception. Also don't have to mock as many objects as I initially thought.
(References to TransformerException here: Java 7 API - Exceptions and Error Reporting )
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.