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)
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 asString
s, and returning them asString
s, but whenever you work with them, you convert them back and forth toint
s. Why not just useint
everywhere in the first place?