【问题标题】:Unable to expect multiple exceptions with JUnit's ExpectedException无法期待 JUnit 的 ExpectedException 出现多个异常
【发布时间】:2013-12-13 14:06:24
【问题描述】:
  • Java 7
  • JUnit 4.11

我正在编写测试来验证我的方法的协定,例如,参数不能为 nullint 参数必须为正等。当违反协定时,抛出的异常类型反映了失败的原因,例如NullPointerExceptionIllegalArgumentException。有时我不在乎这两个中的哪一个被抛出,只是其中一个被抛出。 (是的,我应该测试确切的异常类型,但请耐心等待......)

我可以使用 JUnit 的 @Test(expected = RuntimeException.class)(因为 RuntimeExceptionIAENPE 的最接近的公共父级),但这过于通用,因为被测方法可能会抛出其他一些 RuntimeException

相反,我正在尝试使用 JUnit 的 ExpectedExceptions 类。

这是一个完整的例子:

import org.hamcrest.CoreMatchers;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.anyOf;

public class ParameterViolationTest {
    private Target target = new Target();

    @Rule
    public ExpectedException expected = ExpectedException.none();

    @Test
    public void parameterViolation() {
        expected.expect(anyOf(
                CoreMatchers.<Class<? extends Exception>>
                        equalTo(NullPointerException.class),
                CoreMatchers.<Class<? extends Exception>>
                        equalTo(IllegalArgumentException.class)));

        // Null parameter violates contract, throws some exception.
        target.methodUnderTest(null);
    }

    private static class Target {
        public void methodUnderTest(Object o) {
            if (o == null) {
                // throw new IllegalArgumentException();
                throw new NullPointerException();
            }
        }
    }
}

我希望这个测试能够通过,但结果却失败了:

java.lang.AssertionError: 
Expected: (<class java.lang.NullPointerException> or <class java.lang.IllegalArgumentException>)
     but: was <java.lang.NullPointerException>
Stacktrace was: java.lang.NullPointerException
    at ParameterViolationTest$Target.methodUnderTest(ParameterViolationTest.java:35)
    at ParameterViolationTest.parameterViolation(ParameterViolationTest.java:25)
    < internal calls... >
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    < internal calls... >
java.lang.AssertionError: 
Expected: (<class java.lang.NullPointerException> or <class java.lang.IllegalArgumentException>)
     but: was <java.lang.NullPointerException>
Stacktrace was: java.lang.NullPointerException
    at ParameterViolationTest$Target.methodUnderTest(ParameterViolationTest.java:35)
    at ParameterViolationTest.parameterViolation(ParameterViolationTest.java:25)
    < internal calls... >
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    < internal calls... >
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
    at org.junit.Assert.assertThat(Assert.java:865)
    at org.junit.Assert.assertThat(Assert.java:832)
    at org.junit.rules.ExpectedException.handleException(ExpectedException.java:198)
    at org.junit.rules.ExpectedException.access$500(ExpectedException.java:85)
    at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:177)
    at org.junit.rules.RunRules.evaluate(RunRules.java:20)
    < internal calls... >

这是怎么回事?

【问题讨论】:

    标签: java unit-testing junit


    【解决方案1】:

    您必须使用Matchers.instanceOf 而不是CoreMatchers.equalTo,因为您正在比较XXXException 的实例。

    expected.expect(anyOf(
      instanceOf(NullPointerException.class),
      instanceOf(IllegalArgumentException.class)));
    

    【讨论】:

    • 啊哈,你是对的,而且它更容易阅读。我现在看到 JUnit 正在将抛出异常的实例与我告诉它期望的异常 class 进行比较。 (NullPointerException != class NullPointerException)。这就是它失败的原因。谢谢。
    • 如何将它与每个异常的不同消息结合起来?我期待UnsupportedOperationException("Not supported yet")(没有其他消息)和IllegalArgumentException(任何消息)。
    • anyOf(allOf(...), instanceOf(...))
    猜你喜欢
    • 1970-01-01
    • 2013-12-06
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2018-03-31
    • 1970-01-01
    • 2015-11-20
    • 2015-10-03
    相关资源
    最近更新 更多