Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expect an exception or one of its subclasses in Junit Test using @Test annotation

I have a test that expects a particular exception, for example:

@Test(expected=MyException.class)
public void testMyMethod(){
    myMethod();
}

The myMethod() method actually throws a subclass of MyException, lets call it MySubclassException.

Is there anyway to define my test using the @Test annotation to accept subclasses of MyException as well as the class itself?

I know that I could simply write the test checking logic myself without using expected by catching the exception and setting a flag, but I was wondering whether or not JUnit already supported matching exception subclasses.

like image 345
chrisbunney Avatar asked Jan 10 '12 10:01

chrisbunney


2 Answers

This is already handled for you by the framework

Let's take a small example (very bad code): import static org.junit.Assert.*;

import org.junit.Test;


public class TestExpect {

@Test(expected=MyException.class)
public void test() throws MyException {
    new Foo().foo();
}

}

With 2 exception classes MyException and MyExtendedException inheriting from the previous one and a simple Foo class like this one:

public class Foo {

public void foo() throws MyException{
    throw new MyExtendedException();
}
}

Launching the test using the Eclipse runner prints a green bar because the test raises one instance of Myexception (is a relationship in POO)

If you prefer to read source code this is an exxcerpt from the Junit source code (ExpectException.java):

   @Override
    public void evaluate() throws Exception {
        boolean complete = false;
        try {
            fNext.evaluate();
            complete = true;
        } catch (AssumptionViolatedException e) {
            throw e;
        } catch (Throwable e) {
            if (!fExpected.isAssignableFrom(e.getClass())) {
                String message= "Unexpected exception, expected<"
                            + fExpected.getName() + "> but was<"
                            + e.getClass().getName() + ">";
                throw new Exception(message, e);
            }
        }
        if (complete)
            throw new AssertionError("Expected exception: "
                    + fExpected.getName());
    }
like image 154
romje Avatar answered Oct 23 '22 00:10

romje


The test will pass if MyException or MySubclassException is thrown by myMethod(). I tested the concept with this code:

public class ExceptionTest {

    private static class ExceptionA extends Exception {

    }

    private static class ExceptionB extends ExceptionA {

    }

    @Test(expected=ExceptionA.class)
    public void test() throws Exception {
        throw new ExceptionB();
    }
}
like image 25
Klarth Avatar answered Oct 22 '22 23:10

Klarth