java - update - इलेक्शन रिजल्ट 2018




JUnit: एक लिपटे अपवाद को 'उम्मीद' करना संभव है? (5)

4.11 JUnit के अनुसार आप ExpectedException expectCause() नियम की ExpectedException उपयोग कर सकते हैं expectCause() विधि:

import static org.hamcrest.CoreMatchers.*;

// ...

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

@Test
public void throwsNestedException() throws Exception {
    expectedException.expectCause(isA(SomeNestedException.class));

    throw new ParentException("foo", new SomeNestedException("bar"));
}

मुझे पता है कि कोई भी JUnit में एक 'अपेक्षित' अपवाद को परिभाषित कर सकता है:

@Test(expect=MyException.class)
public void someMethod() { ... }

लेकिन क्या होगा अगर हमेशा एक ही अपवाद फेंका जाए, लेकिन अलग-अलग 'नेस्टेड' कारणों से

कोई सुझाव?


आप अपवादों के लिए एक Matcher बना सकते हैं। यह तब भी काम करता है जब आप Arquillian के @RunWith(Arquillian.class) जैसे किसी अन्य परीक्षण धावक का उपयोग कर रहे हैं, इसलिए आप ऊपर दिए गए @RunWith(ExtendedTestRunner.class) दृष्टिकोण का उपयोग नहीं कर सकते।

यहाँ एक सरल उदाहरण दिया गया है:

public class ExceptionMatcher extends BaseMatcher<Object> {
    private Class<? extends Throwable>[] classes;

    // @SafeVarargs // <-- Suppress warning in Java 7. This usage is safe.
    public ExceptionMatcher(Class<? extends Throwable>... classes) {
        this.classes = classes;
    }

    @Override
    public boolean matches(Object item) {
        for (Class<? extends Throwable> klass : classes) {
            if (! klass.isInstance(item)) {
                return false;
            }   

            item = ((Throwable) item).getCause();
        }   

        return true;
    }   

    @Override
    public void describeTo(Description descr) {
        descr.appendText("unexpected exception");
    }
}

इसके बाद @Rule और ExpectedException साथ इसका उपयोग करें:

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

@Test
public void testSomething() {
    thrown.expect(new ExceptionMatcher(IllegalArgumentException.class, IllegalStateException.class));

    throw new IllegalArgumentException("foo", new IllegalStateException("bar"));
}

2012 में क्रेग रिंगर द्वारा संपादित किया गया: एक उन्नत और अधिक विश्वसनीय संस्करण:

  • मूल उपयोग ऊपर से अपरिवर्तित है
  • बेजोड़ अपवाद को फेंकने के लिए वैकल्पिक 1 तर्क boolean rethrow पास कर सकते हैं। यह आसान डीबगिंग के लिए नेस्टेड अपवादों के स्टैक ट्रेस को संरक्षित करता है।
  • अपाचे कॉमन्स लैंग एक्ससेप्शन यूटिल्स का उपयोग कारण लूप्स को संभालने के लिए और कुछ सामान्य अपवाद वर्गों द्वारा उपयोग किए जाने वाले गैर-मानक अपवाद घोंसले को संभालने के लिए करते हैं।
  • स्व-विवरण में स्वीकृत अपवाद शामिल हैं
  • विफलता पर स्व-वर्णन में शामिल अपवाद का कारण स्टैक शामिल है
  • जावा 7 चेतावनी को संभालें। पुराने संस्करणों पर @SaveVarargs निकालें।

पूर्ण कोड:

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;


public class ExceptionMatcher extends BaseMatcher<Object> {
    private Class<? extends Throwable>[] acceptedClasses;

    private Throwable[] nestedExceptions;
    private final boolean rethrow;

    @SafeVarargs
    public ExceptionMatcher(Class<? extends Throwable>... classes) {
        this(false, classes);
    }

    @SafeVarargs
    public ExceptionMatcher(boolean rethrow, Class<? extends Throwable>... classes) {
        this.rethrow = rethrow;
        this.acceptedClasses = classes;
    }

    @Override
    public boolean matches(Object item) {
        nestedExceptions = ExceptionUtils.getThrowables((Throwable)item);
        for (Class<? extends Throwable> acceptedClass : acceptedClasses) {
            for (Throwable nestedException : nestedExceptions) {
                if (acceptedClass.isInstance(nestedException)) {
                    return true;
                }
            }
        }
        if (rethrow) {
            throw new AssertionError(buildDescription(), (Throwable)item);
        }
        return false;
    }

    private String buildDescription() {
        StringBuilder sb = new StringBuilder();
        sb.append("Unexpected exception. Acceptable (possibly nested) exceptions are:");
        for (Class<? extends Throwable> klass : acceptedClasses) {
            sb.append("\n  ");
            sb.append(klass.toString());
        }
        if (nestedExceptions != null) {
            sb.append("\nNested exceptions found were:");
            for (Throwable nestedException : nestedExceptions) {
                sb.append("\n  ");
                sb.append(nestedException.getClass().toString());
            }
        }
        return sb.toString();
    }

    @Override
    public void describeTo(Description description) {
        description.appendText(buildDescription());
    }

}

विशिष्ट उत्पादन:

java.lang.AssertionError:  Expected: Unexpected exception. Acceptable (possibly nested) exceptions are:
   class some.application.Exception
Nested exceptions found were:
   class javax.ejb.EJBTransactionRolledbackException
   class javax.persistence.NoResultException
     got: <javax.ejb.EJBTransactionRolledbackException: getSingleResult() did not retrieve any entities.>

आप परीक्षण कोड को एक कोशिश / कैच ब्लॉक में लपेट सकते हैं, फेंके गए अपवाद को पकड़ सकते हैं, आंतरिक कारण की जांच कर सकते हैं, लॉग / एसेर / जो भी कर सकते हैं, और फिर अपवाद (यदि वांछित हो) को रीथ्रो कर सकते हैं।


मैंने उस उद्देश्य के लिए थोड़ा JUnit एक्सटेंशन लिखा। एक स्थैतिक सहायक फ़ंक्शन एक फ़ंक्शन बॉडी और अपेक्षित अपवादों की एक सरणी लेता है:

import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Arrays;

public class AssertExt {
    public static interface Runnable {
        void run() throws Exception;
    }

    public static void assertExpectedExceptionCause( Runnable runnable, @SuppressWarnings("unchecked") Class[] expectedExceptions ) {
        boolean thrown = false;
        try {
            runnable.run();
        } catch( Throwable throwable ) {
            final Throwable cause = throwable.getCause();
            if( null != cause ) {
                assertTrue( Arrays.asList( expectedExceptions ).contains( cause.getClass() ) );
                thrown = true;
            }
        }
        if( !thrown ) {
            fail( "Expected exception not thrown or thrown exception had no cause!" );
        }
    }
}

अब आप अपेक्षित नेस्टेड अपवादों के लिए जाँच कर सकते हैं:

import static AssertExt.assertExpectedExceptionCause;

import org.junit.Test;

public class TestExample {
    @Test
    public void testExpectedExceptionCauses() {
        assertExpectedExceptionCause( new AssertExt.Runnable(){
            public void run() throws Exception {
                throw new Exception( new NullPointerException() );
            }
        }, new Class[]{ NullPointerException.class } );
    }
}

यह आपको एक ही बॉयलर प्लेट कोड को बार-बार लिखने से बचाता है।


सबसे संक्षिप्त सिंटैक्स catch-exception द्वारा प्रदान किया जाता catch-exception :

import static com.googlecode.catchexception.CatchException.*;

catchException(myObj).doSomethingNasty();
assertTrue(caughtException().getCause() instanceof MyException);






junit