views:

129

answers:

6

This might be a conceptually stupid question, but it also might not and since I am still a student I think I should I have no problem asking.

Imagine you have a method that if given certain conditions it will throw an NumberFormatException. I want to write a Unit Test to see if the exception is being correctly thorwn. How can I achieve this?

P.S. I am using JUnit to write the Unit Tests.

Thanks.

+2  A: 

Use @Test(expected=IOException.class)

http://junit.sourceforge.net/doc/faq/faq.htm#tests_7

This is fine if you have one expected exception. An alternative strategy is to add an Assert.fail() at the end of the test method. If an exception isn't thrown then the test will fail accordingly. e.g.

@Test
public void testIOExceptionThrown() {      
   ftp.write(); // will throw IOException      
   fail();
}
Jon
+10  A: 

As other posters suggested, if you are using JUnit4, then you can use the annotation:

@Test(expected=NumberFormatException.class);

However, if you are using an older version of JUnit, or if you want to do multiple "Exception" assertions in the same test method, then the standard idiom is:

try {
   formatNumber("notAnumber");
   fail("Expected NumberFormatException");
catch(NumberFormatException e) {
  // no-op (pass)
}
Michael D
This is a good idiom for when you want to test things about the exception, such as its message, not just its existence.
Yishai
+1 - Good point about the older version.
Feanor
+1 - An answer to this question is not complete without the second example. In practice I need to default to this approach more often than not for the reasons mentioned.
Synesso
The problem with doing this, is that I've seen a lot of people mess up the boilerplate. (ie: forgetting to call fail, or catching too general of an exception). Personally, I prefer to create a method that takes a Runnable or Callable (for checked exceptions) and asserts that it throws a given exception. (ie: assertException(NumberFormatException.class, new Callable<Void>() { ... formatNumber("notAnumber"); });. It's just as much boilerplate, but "feels safer"
Michael D
I generally check the message and maybe other fields of the caught exception.
Stephen C
@Michael D: Would you care to elaborate your comment and maybe add a answer of your own. I think like your idea.
nunos
+8  A: 

Assuming you are using JUnit 4, call the method in your test in a way that causes it to throw the exception, and use the JUnit annotation

@Test(expected = NumberFormatException.class)

If the exception is thrown, the test will pass.

Feanor
+1 - Fast, boy.
duffymo
@duffymo: Thanks! :)
Feanor
+3  A: 

You can do this:

 @Test(expected=IndexOutOfBoundsException.class)
    public void testIndexOutOfBoundsException() {
        ArrayList emptyList = new ArrayList();
        Object o = emptyList.get(0);
    }
Adam
+1  A: 
@Test(expected="java.lang.NumberFormatException")

This annotation will do the trick.

duffymo
+3  A: 

If you can use JUnit 4.7, you can use the ExpectedException Rule

@RunWith(JUnit4.class)
public class FooTest {
  @Rule
  public ExpectedException exception = ExpectedException.none();

  @Test
  public void doStuffThrowsIndexOutOfBoundsException() {
    Foo foo = new Foo();

    exception.expect(IndexOutOfBoundsException.class);
    exception.expectMessage("happened?");
    exception.expectMessage(startsWith("What"));
    foo.doStuff();
  }
}

This is much better than @Test(expected=IndexOutOfBoundsException.class) because the test will fail if IndexOutOfBoundsException is thrown before foo.doStuff()

See this article and the ExpectedException JavaDoc for details

NamshubWriter
For in depth reasoning and explanation I would like to recommend this article: http://monkeyisland.pl/2010/07/26/expected-exception-in-tests/+1 from me.
Alex Nikolaenkov