I have a function which returns an exception and i am writing a unit test case for it in Junit4. The issue is, reflect.invoke always wraps the exception in InvocationTargetException and hence unable to check the exception using ExpectedException class.
public class Hello {
private void printHello(String msg) {
if ("hello".equals(msg)) {
System.out.println("Hello");
}
else throw new HeaderException();
}
}
Test:
@Rule
public ExpectedException expectedEx = ExpectedException.none();
@Test
public void testPrint() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
expectedEx.expect(HeaderException.class);
Method method = Hello.class.getDeclaredMethod("printHello", String.class);
method.setAccessible(true);
method.invoke(Hello.class,"random");
}
Output:
java.lang.AssertionError:
Expected: an instance of com.locationguru.CSF.exception.HeaderException
got: <java.lang.reflect.InvocationTargetException>
<Click to see difference>
at org.junit.Assert.assertThat(Assert.java:780)
at org.junit.Assert.assertThat(Assert.java:738)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:114)
at org.junit.rules.RunRules.evaluate(RunRules.java:18)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
When using JUnit 4, we can simply use the expected attribute of the @Test annotation to declare that we expect an exception to be thrown anywhere in the annotated test method. In this example, we've declared that we're expecting our test code to result in a NullPointerException.
To verify the fields of an exception you'd have to add a try/catch within the test case, and within the catch block perform the additional assertions and then throw the caught exception. When using ExpectedException you have to initially declare it with none() , no exception expected, which is a bit confusing.
Test Exception in JUnit 4 @Rule public ExpectedException exception = ExpectedException. none(); Then in the test method you can use its expect() and expectMessage() to assert the type of expected exception and the exception message.
One way of doing it could be to throw again the expected error , but is it recommended
try
{
method.invoke(Hello.class, "random");
}
catch (InvocationTargetException e)
{
throw e.getTargetException();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With