问题
I would like to test the return code of an exception. Here is my production code:
class A {
try {
something...
}
catch (Exception e)
{
throw new MyExceptionClass(INTERNAL_ERROR_CODE, e);
}
}
And the corresponding exception:
class MyExceptionClass extends ... {
private errorCode;
public MyExceptionClass(int errorCode){
this.errorCode = errorCode;
}
public getErrorCode(){
return this.errorCode;
}
}
My unit test:
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();
}
}
回答1:
Simple:
@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));
}
That is all you need here:
- you don't want to expect that specific exception, as you want to check some properties of it
- you know that you want to enter that specific catch block; thus you simply fail when the call doesn't throw
- you don't need any other checking - when the method throws any other exception, JUnit will report that as error anyway
回答2:
You can check for it using hamcres matchers as long as thrown.expect
is overload to receive Matcher
thrown.expect(CombinableMatcher.both(
CoreMatchers.is(CoreMatchers.instanceOf(MyExceptionClass.class)))
.and(Matchers.hasProperty("errorCode", CoreMatchers.is(123))));
Note that you will need to add hamcrest matcher to your dependencies. Core matched that are included in JUnit is not enough.
Or if you don't want to use CombinableMatcher:
thrown.expect(CoreMatchers.instanceOf(MyExceptionClass.class));
thrown.expect(Matchers.hasProperty("errorCode", CoreMatchers.is(123));
Also, you don't need (expected = MyExceptionClass.class)
declaration for @Test
annotation
回答3:
Expanding upon Sergii's answer, you can clean this up even more by writing a custom matcher.
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);
}
}
The error code can then be checked like:
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();
}
}
Reference: https://dzone.com/articles/testing-custom-exceptions
来源:https://stackoverflow.com/questions/43179242/test-the-error-code-of-a-custom-exception-with-junit-4