Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JUnit 4 Expected Exception type

I am trying to do a JUnit test on code that someone else has written, but I cannot figure out how to test for the exception, because the exception seems to lack a type.

public Pirate(String name, int initialGold) throws Exception {
    if(initialGold < 0)
        throw new Exception("Init Gold must be >= 0");
    this.name = name;
    this.numGold = initialGold;
    this.health = Pirate.DEFAULT_HEALTH;
    this.isCursed = false;
}

My JUnit Code snippet:

@Test
public static void constructorTest() throws Exception{
    rodgers = new Pirate("Dread Pirate Rodgers", 10000);
    assertEquals("Dread Pirate Rodgers" , rodgers.getName());
    assertEquals(10000, rodgers.getNumGold());
    assertEquals(100, rodgers.getHealth());
    assertEquals(false, rodgers.getIsCursed());
}

@Test()
public static void exceptionTest() throws Exception{
    rodgers = new Pirate("Dread Pirate Rodgers" , -100);

}

I know I need to put expected = (some type of exception) in the parenthesis of test, but I am clueless as to the exception type.

like image 692
Marshall Tigerus Avatar asked May 23 '13 20:05

Marshall Tigerus


People also ask

How does JUnit 4 handle exceptions?

JUnit provides an option of tracing the exception handling of code. You can test whether the code throws a desired exception or not. The expected parameter is used along with @Test annotation. Let us see @Test(expected) in action.

How does JUnit handle expected exception?

In JUnit, there are 3 ways to test the expected exceptions : @Test , optional 'expected' attribute. Try-catch and always fail() @Rule ExpectedException.

How do you test exceptions in JUnit 4?

When using JUnit 4, we can simply use the expected attribute of the @Test annotation to declare that we expect an exception to be thrown anywhere in the annotated test method.

What is expected exception?

The ExpectedException rule allows you to verify that your code throws a specific exception.


3 Answers

There's actually an alternative to the @Test(expected=Xyz.class) in JUnit 4.7 using Rule and ExpectedException

In your test case you declare an ExpectedException annotated with @Rule, and assign it a default value of ExpectedException.none(). Then in your test that expects an exception you replace the value with the actual expected value. The advantage of this is that without using the ugly try/catch method, you can further specify what the message within the exception was

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

@Test
public void myTest() {
    thrown.expect( Exception.class );
    thrown.expectMessage("Init Gold must be >= 0");

    rodgers = new Pirate("Dread Pirate Rodgers" , -100);
}

Using this method, you might be able to test for the message in the generic exception to be something specific.

ADDITION Another advantage of using ExpectedException is that you can more precisely scope the exception within the context of the test case. If you are only using @Test(expected=Xyz.class) annotation on the test, then the Xyz exception can be thrown anywhere in the test code -- including any test setup or pre-asserts within the test method. This can lead to a false positive.

Using ExpectedException, you can defer specifying the thrown.expect(Xyz.class) until after any setup and pre-asserts, just prior to actually invoking the method under test. Thus, you more accurately scope the exception to be thrown by the actual method invocation rather than any of the test fixture itself.

JUnit 5 NOTE:

JUnit 5 JUnit Jupiter has removed @Test(expected=...), @Rule and ExpectedException altogether. They are replaced with the new assertThrows(), which requires the use of Java 8 and lambda syntax. ExpectedException is still available for use in JUnit 5 through JUnit Vintage. Also JUnit Jupiter will also continue to support JUnit 4 ExpectedException through use of the junit-jupiter-migrationsupport module, but only if you add an additional class-level annotation of @EnableRuleMigrationSupport.

like image 192
Kevin Welker Avatar answered Oct 16 '22 06:10

Kevin Welker


You could either use expected in @Test annotation or provide an explicit catch block and issue a fail if the program flow is not as expected.

@Test(expected=Exception.class) // java.lang.Exception
public static void exceptionTest() throws Exception {
    rodgers = new Pirate("Dread Pirate Rodgers" , -100);
}

@Test
public static void exceptionTest() throws Exception {
    try {
        rodgers = new Pirate("Dread Pirate Rodgers" , -100);
        fail("should not reach this");
    } catch(Exception e) {
        // ok
    }
}

My personal preference is the first solution.

like image 20
Steve Oh Avatar answered Oct 16 '22 07:10

Steve Oh


You can use JUnit 'expected' to test exceptions:

@Test(expected = ExceptionYouWishToTestFor.class)  
public void divisionWithException() {  
    // Test Code
}

After that it's up to you to throw that particular exception in your code.

like image 9
Michael W Avatar answered Oct 16 '22 08:10

Michael W