Reputation: 1035
I'm trying to test my class for a Exception. I've been trying a couple different methods, nothing works. What am I doing wrong here?
The class I'm trying to test, PrimeNumber.java:
public class PrimeNumber {
static final Logger LOG = LogManager.getLogger("Log");
private String primeNumberStr;
public PrimeNumber(String primeNumberStr) {
this.primeNumberStr = primeNumberStr;
}
public String getPrimeResult() {
String resultStr = "";
try {
// Convert user input to int
int primeNumberInt = Integer.parseInt(primeNumberStr);
// Beginning of return message
resultStr += primeNumberInt + " is ";
// Add "not" if it's not a prime
if (!Primes.isPrime(primeNumberInt))
resultStr += "NOT ";
// End return message
resultStr += "a prime";
// If not a valid number, catch
} catch (NumberFormatException e) {
// Log exception
LOG.warn("NumberFormatException" + e.getMessage());
// If empty user input
if (primeNumberStr.length() == 0)
resultStr += "No number inserted";
// Else not empty but not valid
else
resultStr += primeNumberStr + " is not a valid number";
resultStr += ". Only numbers without decimals are accepted.";
}
return resultStr;
}
}
And now things I've tried to test:
With annotation
@Test(expected = NumberFormatException.class)
public void testNumberFormatExceptionBeingThrown() {
PrimeNumber primeNumber = new PrimeNumber("6dg");
primeNumber.getPrimeResult();
}
Results in failed test and:
java.lang.AssertionError: Expected exception: java.lang.Exception
With a JUnit rule:
@Rule public ExpectedException thrown = ExpectedException.none();
@Test(expected = NumberFormatException.class)
public void testNumberFormatExceptionBeingThrown() {
thrown.expect(NumberFormatException.class);
thrown.expectMessage("For input string: \"a21\"");
PrimeNumber primeNumber = new PrimeNumber("a21");
primeNumber.getPrimeResult();
}
Results in:
java.lang.AssertionError: Expected test to throw (an instance of java.lang.NumberFormatException and exception with message a string containing "For input string: \"a21\"")
at org.junit.Assert.fail(Assert.java:88)
at org.junit.rules.ExpectedException.failDueToMissingException(ExpectedException.java:263)
at org.junit.rules.ExpectedException.access$200(ExpectedException.java:106)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:245)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
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:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Upvotes: 2
Views: 21844
Reputation: 9137
Everything's working as it should. You've successfully been able to prevent your methods from throwing exceptions. You've successfully been able to test that they do throw exceptions.
It's just, it doesn't make sense to do both at the same time. You need to decide if you want each method to throw an exception or not when given wrong arguments.
If you do want a method to throw an exception when given a wrong argument, then don't catch and handle the exception, just let it be thrown. Then, test that your method throws that exception, like you did above.
If you don't want the method to throw an exception when given a wrong argument, then decide what you want it to do instead. Then, test that your method does what you want it to. If it throws an exception, the test will fail.
That said, the way you handle numbers in your class doesn't make much sense. You're getting them as String
s, storing them as String
s, and returning them as String
s, but whenever you work with them, you convert them back and forth to int
s. Why not just use int
everywhere in the first place?
Upvotes: 2
Reputation: 106389
Your getPrimeResult
is actually dealing with the exception as opposed to allowing it to propagate any further in the call stack. Hence, it's not being thrown, and the test will never be able to intercept it and assert against it (in that state).
While I think that this is a better approach, if you want to propagate it through the call stack, you would need to throw
it after you've caught it.
// after the assignment to resultStr
throw e;
Upvotes: 1