Ajay Yadav
Ajay Yadav

Reputation: 806

Alternative to @Test(expected=ExceptionClass.class) for testing exceptions in testng

In TestNG, when we want to test a scenario in which an exception should be thrown one can write something like the following

@Test(expected=IndexOutOfBoundsException.class, expectedExceptionsMessageRegExp="*")
public void sampleExpectedExceptionTest() {
    List emptyList = new ArrayList();
    // Following line should throw an IndexOutOfBoundsException
    emptyList.get(0);
} 

I have seen that some people write the tests in following style.

@Test
public void sampleExpectedExceptionTest() {
  // several lines here..

  List emptyList = new ArrayList();
  try {
    emptyList.get(0);
    Assert.assertFail("Expected IndexOutOfBoundsException but wasn't thrown");
  } catch (IndexOutOfBoundsException e) {
    // ignore
  }

  // ... more lines of code asserting exceptions similar to above try catch scenario
}

I dislike the above style primarily because it is very verbose and also because people using it usually write multiple tests in one test case. However, the argument given in it's favour is that it allows users to pinpoint the assertion to a particular line and hence it is better.

Recently I learnt about JUnit's @Rule annotation

public class SampleExceptionTest {
   @Rule
   public final ExpectedException exception = ExpectedException.none();

   @Test
   public void sampleExpectedExceptionTest() {
       List emptyList = new ArrayList();

       exception.expect(IndexOutOfBoundsException.class);
       emptyList.get(0);
   }
}

This not only allows users to pinpoint the assertion to a line but it also discourages users to write multiple tests in one test case as once an exception is thrown the code exits and you can not test for multiple assertions. I want to know is there a similar option (or an idiom) in TestNG? I know that I can use expected

Upvotes: 0

Views: 1389

Answers (1)

Adam Michalik
Adam Michalik

Reputation: 9955

I suggest you have a look at the Catch-Exception library. It allows you to perform multiple assertions on the exception and any other relevant assertions. You can use it with JUnit and TestNG and any assertion framework you want.

Sample:

@Test
public void catchExceptionTest() {
    // given: an empty list
    List<Object> myList = new ArrayList<>();

    // when: we try to get the first element of the list
    // then: catch the exception if any is thrown
    catchException(myList).get(1);

    // then: we expect an IndexOutOfBoundsException
    Exception e = caughtException();
    // Use JUnit, TestNG, AssertJ etc. assertions on the "e" exception
    assert e instanceof IndexOutOfBoundsException;
}

You'll find more examples on the project page.

Upvotes: 1

Related Questions