أفضل طريقة للتحقق من ما إذا كان نوع الاستثناء كان السبب (سبب ... الخ) في تداخل استثناء ؟

StackOverflow https://stackoverflow.com/questions/610628

سؤال

أنا أكتب بعض JUnit الاختبارات التي تحقق هذا استثناء من نوع MyCustomException يتم طرح.غير أن هذا الاستثناء هو ملفوفة في استثناءات أخرى عدة مرات ، على سبيل المثالفي InvocationTargetException ، والتي بدورها هي ملفوفة في RuntimeException.

ما هي أفضل طريقة لتحديد ما إذا كان MyCustomException بطريقة ما تسبب في الاستثناء أن أنا فعلا الصيد ؟ وأود أن تفعل شيئا من هذا القبيل (انظر أكد):


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

وأود أن تجنب استدعاء getCause() عدد قليل من "طبقات" عميقة مماثلة القبيح العمل-احترف.هل هناك أجمل الطريقة ؟

(على ما يبدو الربيع NestedRuntimeException.يحتوي على(فئة), الذي يفعل ما أريد - ولكن أنا لا تستخدم الربيع.)

مغلقة: حسنا, أعتقد أن هناك حقا لا يمكن الالتفاف حول فائدة الطريقة :-) شكرا لكل من أجاب!

هل كانت مفيدة؟

المحلول

لماذا كنت ترغب في تجنب getCause.يمكنك بالطبع تكتب لنفسك طريقة لأداء هذه المهمة ، شيء من هذا القبيل:

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

نصائح أخرى

إذا كنت تستخدم أباتشي العموم لانج, ثم يمكنك استخدام ما يلي:

(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
}

أنا لا أعتقد أن لديك أي خيار سوى أن ندعو من خلال طبقات من getCause.إذا نظرتم إلى التعليمات البرمجية المصدر الربيع 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;
    }
}

التحذير:أعلاه هو رمز اعتبارا من 4 آذار / مارس 2009 حتى, إذا كنت تريد حقا أن تعرف ما الربيع تفعل الآن, يجب عليك البحث في التعليمات البرمجية كما هو موجود اليوم (متى).

أعتقد ليس هناك طريقة للقيام بذلك دون استدعاء getCause().انها تعتقد انها قبيحة تنفيذ فائدة فئة للقيام بذلك:

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

يمكنك القيام بذلك باستخدام الجوافة:

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

على أساس باتريك الاستهجان الجواب:إذا كنت تستخدم Apache العموم Lang 3 يمكنك التحقق من:

indexOfThrowable:ترجع (على أساس الصفر) مؤشر أول Throwable أن مباريات الفئة المحددة (بالضبط) في الاستثناء سلسلة. فرعية من الفئة المحددة لا تتطابق

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

أو

indexOfType:ترجع (على أساس الصفر) مؤشر أول Throwable أن المباريات المحددة فئة أو فئة فرعية في الاستثناء سلسلة. فرعية من الفئة المحددة لا تتطابق

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

مثال لأنواع متعددة مع جافا 8:

Class<? extends Throwable>[] classes = {...}
boolean match = Arrays.stream(classes)
            .anyMatch(clazz -> ExceptionUtils.indexOfType(e, clazz) != -1);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top