【问题标题】:Test the error code of a custom exception with JUnit 4使用 JUnit 4 测试自定义异常的错误代码
【发布时间】:2017-08-28 00:02:22
【问题描述】:

我想测试异常的返回码。这是我的生产代码:

class A {
  try {
    something...
  }
  catch (Exception e)
  {
    throw new MyExceptionClass(INTERNAL_ERROR_CODE, e);
  }
}

以及对应的异常:

class MyExceptionClass extends ... {
  private errorCode;

  public MyExceptionClass(int errorCode){
    this.errorCode = errorCode;
  }

  public getErrorCode(){ 
    return this.errorCode;
  }
}

我的单元测试:

public class AUnitTests{
  @Rule
  public ExpectedException thrown= ExpectedException.none();

  @Test (expected = MyExceptionClass.class, 
  public void whenRunningSomething_shouldThrowMyExceptionWithInternalErrorCode() throws Exception {
      thrown.expect(MyExceptionClass.class);
      ??? expected return code INTERNAL_ERROR_CODE ???

      something();
  }
}

【问题讨论】:

  • 我正在寻找一个很好的方法来做到这一点。 Try/catch 没问题,但这意味着更多的代码行。在我看来,这很难读......
  • 请检查我的回答,希望这种方法对你有帮助

标签: java junit junit4 junit-rule


【解决方案1】:

扩展 Sergii 的答案,您可以通过编写自定义匹配器来进一步清理它。

import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class CustomMatcher extends TypeSafeMatcher<CustomException> {

    public static CustomMatcher hasCode(String item) {
        return new CustomMatcher(item);
    }

    private String foundErrorCode;
    private final String expectedErrorCode;

    private CustomMatcher(String expectedErrorCode) {
        this.expectedErrorCode = expectedErrorCode;
    }

    @Override
    protected boolean matchesSafely(final CustomException exception) {
        foundErrorCode = exception.getErrorCode();
        return foundErrorCode.equalsIgnoreCase(expectedErrorCode);
    }

    @Override
    public void describeTo(Description description) {
        description.appendValue(foundErrorCode)
                .appendText(" was not found instead of ")
                .appendValue(expectedErrorCode);
    }
}

然后可以检查错误代码,如下所示:

import org.junit.rules.ExpectedException;

public class MyObjTest {

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

    @Test
    public void someMethodThatThrowsCustomException() {
        thrown.expect(CustomException.class);
        thrown.expect(CustomMatcher.hasCode("110501"));

        MyObj obj = new MyObj();
        obj.methodThatThrowsCustomException();
    }
}

参考:https://dzone.com/articles/testing-custom-exceptions

【讨论】:

    【解决方案2】:

    只要thrown.expect 超载接收Matcher,您就可以使用hamcres 匹配器检查它

    thrown.expect(CombinableMatcher.both(
               CoreMatchers.is(CoreMatchers.instanceOf(MyExceptionClass.class)))
               .and(Matchers.hasProperty("errorCode", CoreMatchers.is(123))));
    

    请注意,您需要将 hamcrest 匹配器添加到您的依赖项中。包含在 JUnit 中的核心匹配是不够的。

    或者如果您不想使用 CombinableMatcher:

    thrown.expect(CoreMatchers.instanceOf(MyExceptionClass.class));
    thrown.expect(Matchers.hasProperty("errorCode", CoreMatchers.is(123));
    

    另外,@Test 注释不需要 (expected = MyExceptionClass.class) 声明

    【讨论】:

    • 不错!谢谢!
    【解决方案3】:

    简单:

     @Test 
     public void whenSerialNumberIsEmpty_shouldThrowSerialNumberInvalid() throws Exception {
      try{
         whenRunningSomething_shouldThrowMyExceptionWithInternalErrorCode();     
         fail("should have thrown");
      }
      catch (MyExceptionClass e){
         assertThat(e.getCode(), is(MyExceptionClass.INTERNAL_ERROR_CODE));
      }
    

    这就是你所需要的:

    • 您不想期待那个特定的异常,因为您想要检查它的某些属性
    • 你知道你想要进入那个特定的catch块;因此,当调用没有抛出时,您只会失败
    • 您不需要任何其他检查 - 当方法抛出任何其他异常时,JUnit 无论如何都会将其报告为错误

    【讨论】:

      猜你喜欢
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-18
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 2010-12-22
      相关资源
      最近更新 更多