문제

나는 유형의 예외를 확인하는 Junit 테스트를 작성하고 있습니다. MyCustomException 던져졌다. 그러나이 예외는 다른 예외에 여러 번, 예를 들어 invocationtargetexception에서 랩핑됩니다.

mycustomexception이 어떻게 든 내가 실제로 잡는 예외를 유발했는지 여부를 결정하는 가장 좋은 방법은 무엇입니까? 나는 이런 일을하고 싶습니다 (밑줄 참조) :


try {
    doSomethingPotentiallyExceptional();
    fail("Expected an exception.");
} catch (RuntimeException e) {
     if (!e.wasCausedBy(MyCustomException.class)
        fail("Expected a different kind of exception.");
}

전화를 피하고 싶습니다 getCause() 몇 개의 "레이어"깊이와 비슷한 못생긴 작업 계약. 더 좋은 방법이 있습니까?

(분명히, 봄은 있습니다 NestEdRuntImeexception.contains (클래스), 내가 원하는 것을하는 일 - 그러나 나는 봄을 사용하지 않습니다.)

닫은:좋아, 유틸리티 방법을 돌아 다니는 것이 실제로 없을 것 같아요 :-) 대답 한 모든 분들께 감사드립니다!

도움이 되었습니까?

해결책

왜 피하고 싶습니까? getCause. 물론 다음과 같은 작업을 수행하는 방법을 작성할 수 있습니다.

public static boolean isCause(
    Class<? extends Throwable> expected,
    Throwable exc
) {
   return expected.isInstance(exc) || (
       exc != null && isCause(expected, exc.getCause())
   );
}

다른 팁

사용중인 경우 Apache Commons Lang, 그런 다음 다음을 사용할 수 있습니다.

(1) 원인이 정확히 지정된 유형이어야하는 경우

if (ExceptionUtils.indexOfThrowable(exception, ExpectedException.class) != -1) {
    // exception is or has a cause of type ExpectedException.class
}

(2) 원인이 지정된 유형 또는 서브 클래스 유형이어야하는 경우

if (ExceptionUtils.indexOfType(exception, ExpectedException.class) != -1) {
    // exception is or has a cause of type ExpectedException.class or its subclass
}

나는 당신이 선택의 여지가 없다고 생각합니다. Spring NestedRuntImeexception의 소스 코드를 살펴보면 그것이 구현되는 방법입니다.

모방은 진심으로 아첨의 형태입니다. 소스의 빠른 검사를 기반으로합니다, 이것이 바로 NestEdRuntImeexception이하는 일입니다.

/**
 * Check whether this exception contains an exception of the given type:
 * either it is of the given class itself or it contains a nested cause
 * of the given type.
 * @param exType the exception type to look for
 * @return whether there is a nested exception of the specified type
 */
public boolean contains(Class exType) {
    if (exType == null) {
        return false;
    }
    if (exType.isInstance(this)) {
        return true;
    }
    Throwable cause = getCause();
    if (cause == this) {
        return false;
    }
    if (cause instanceof NestedRuntimeException) {
        return ((NestedRuntimeException) cause).contains(exType);
    }
    else {
        while (cause != null) {
            if (exType.isInstance(cause)) {
                return true;
            }
            if (cause.getCause() == cause) {
                break;
            }
            cause = cause.getCause();
        }
        return false;
    }
}

경고: 위는 2009 년 3 월 4 일 현재 코드이므로 Spring이 지금 무엇을하고 있는지 알고 싶다면 오늘날에 존재하는대로 코드를 조사해야합니다.

글쎄, 나는 전화하지 않고 이것을 할 방법이 없다고 생각합니다 getCause(). 그것은 그것이 추악한 구현이라고 생각합니다 공익사업 이 작업을위한 수업 :

public class ExceptionUtils {
     public static boolean wasCausedBy(Throwable e, Class<? extends Throwable>) {
         // call getCause() until it returns null or finds the exception
     }
}

Guava를 사용 하여이 작업을 수행 할 수 있습니다.

FluentIterable.from(Throwables.getCausalChain(e))
                        .filter(Predicates.instanceOf(ConstraintViolationException.class))
                        .first()
                        .isPresent();

Patrick Boos를 기반으로 답변 : Apache Commons Lang 3을 사용하는 경우 다음을 확인할 수 있습니다.

indexofthrowable: 지정된 클래스와 일치하는 첫 번째 던지기 가능의 (제로 기반) 색인을 반환합니다 (바로 그거죠) 예외 체인에서. 지정된 클래스의 서브 클래스가 일치하지 않습니다

if (ExceptionUtils.indexOfThrowable(e, clazz) != -1) {
    // your code
}

또는

indexoftype: 지정된 것과 일치하는 첫 번째 던지기 가능의 (제로 기반) 색인을 반환합니다. 클래스 또는 하위 클래스 예외 체인에서. 지정된 클래스의 서브 클래스가 일치합니다

if (ExceptionUtils.indexOfType(e, clazz) != -1) {
    // your code
}

Java 8의 여러 유형에 대한 예 :

Class<? extends Throwable>[] classes = {...}
boolean match = Arrays.stream(classes)
            .anyMatch(clazz -> ExceptionUtils.indexOfType(e, clazz) != -1);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top