JUnit: Test exception doesn't work (AssertionError: Expected exception even if exception thrown)
JUnit: Test exception doesn't work (AssertionError: Expected exception even if exception thrown)
我正在尝试测试我的 class 异常。我一直在尝试几种不同的方法,但没有任何效果。我在这里做错了什么?
我正在尝试测试的 class,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;
}
}
现在我尝试测试的东西:
有注释
@Test(expected = NumberFormatException.class)
public void testNumberFormatExceptionBeingThrown() {
PrimeNumber primeNumber = new PrimeNumber("6dg");
primeNumber.getPrimeResult();
}
测试失败的结果和:
java.lang.AssertionError: Expected exception: java.lang.Exception
使用 JUnit 规则:
@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();
}
结果:
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.access0(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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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)
您的 getPrimeResult
实际上是在处理异常,而不是允许它在调用堆栈中进一步传播。因此,它不会被抛出,并且测试将永远无法拦截它并对其进行断言(在那种状态下)。
虽然我认为这是一种更好的方法,但如果您想通过调用堆栈传播它,则需要在捕获它之后 throw
它。
// after the assignment to resultStr
throw e;
一切正常。您已经成功地防止 您的方法抛出异常。您已经成功地能够测试它们确实抛出异常。
只是,两者同时做没有意义。 您需要决定是否希望每个方法在给定错误参数时抛出异常。
如果您希望方法在给定错误参数时抛出异常,则不要捕获和处理异常,让它抛出即可。然后,像上面那样测试您的方法是否抛出该异常。
如果您不希望该方法在给定错误参数时抛出异常,那么请决定您希望它做什么。然后,测试您的方法是否按照您的意愿进行。如果抛出异常,测试将失败。
也就是说,您在 class 中处理数字的方式没有多大意义。您将它们作为 String
s 获取,将它们存储为 String
s,并将它们作为 String
s 返回,但是无论何时使用它们,您都将它们来回转换为 int
秒。为什么不一开始就到处使用 int
?
我正在尝试测试我的 class 异常。我一直在尝试几种不同的方法,但没有任何效果。我在这里做错了什么?
我正在尝试测试的 class,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;
}
}
现在我尝试测试的东西:
有注释
@Test(expected = NumberFormatException.class)
public void testNumberFormatExceptionBeingThrown() {
PrimeNumber primeNumber = new PrimeNumber("6dg");
primeNumber.getPrimeResult();
}
测试失败的结果和:
java.lang.AssertionError: Expected exception: java.lang.Exception
使用 JUnit 规则:
@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();
}
结果:
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.access0(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.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=14=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.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)
您的 getPrimeResult
实际上是在处理异常,而不是允许它在调用堆栈中进一步传播。因此,它不会被抛出,并且测试将永远无法拦截它并对其进行断言(在那种状态下)。
虽然我认为这是一种更好的方法,但如果您想通过调用堆栈传播它,则需要在捕获它之后 throw
它。
// after the assignment to resultStr
throw e;
一切正常。您已经成功地防止 您的方法抛出异常。您已经成功地能够测试它们确实抛出异常。
只是,两者同时做没有意义。 您需要决定是否希望每个方法在给定错误参数时抛出异常。
如果您希望方法在给定错误参数时抛出异常,则不要捕获和处理异常,让它抛出即可。然后,像上面那样测试您的方法是否抛出该异常。
如果您不希望该方法在给定错误参数时抛出异常,那么请决定您希望它做什么。然后,测试您的方法是否按照您的意愿进行。如果抛出异常,测试将失败。
也就是说,您在 class 中处理数字的方式没有多大意义。您将它们作为 String
s 获取,将它们存储为 String
s,并将它们作为 String
s 返回,但是无论何时使用它们,您都将它们来回转换为 int
秒。为什么不一开始就到处使用 int
?