How do you unittest exceptions in Dart?

I like this approach:

test('when start > stop', () {
  try {
    range(5, 3);
  } on ArgumentError catch(e) {
    expect(e.message, 'start must be less than stop');
    return;
  }
  throw new ExpectException("Expected ArgumentError");  
});

As a more elegant solution to @Shailen Tuli's proposal, if you want to expect an error with a specific message, you can use having.

In this situation, you are looking for something like this:

expect(
  () => range(5, 3),
  throwsA(
    isA<ArgumentError>().having(
      (error) => error.message,        // The feature you want to check.
      'message',                       // The description of the feature.
      'start must be less than stop',  // The error message.
    ),
  ),
);

In this case, there are various ways to test the exception. To simply test that an unspecific exception is raised:

expect(() => range(5, 5), throwsException);

to test that the right type of exception is raised:

there are several predefined matchers for general purposes like throwsArgumentError, throwsRangeError, throwsUnsupportedError, etc.. for types for which no predefined matcher exists, you can use TypeMatcher<T>.

expect(() => range(5, 2), throwsA(TypeMatcher<IndexError>()));

to ensure that no exception is raised:

expect(() => range(5, 10), returnsNormally);

to test the exception type and exception message:

expect(() => range(5, 3), 
    throwsA(predicate((e) => e is ArgumentError && e.message == 'start must be less than stop')));

here is another way to do this:

expect(() => range(5, 3), 
  throwsA(allOf(isArgumentError, predicate((e) => e.message == 'start must be less than stop'))));

(Thanks to Graham Wheeler at Google for the last 2 solutions).


An exception is checked using throwsA with TypeMatcher.

Note: isInstanceOf is now deprecated.

List range(start, stop) {
    if (start >= stop) {
      throw new ArgumentError("start must be less than stop");
    }
    // remainder of function
}


test("check argument error", () {
  expect(() => range(1, 2), throwsA(TypeMatcher<ArgumentError>()));
}); 

Tags:

Dart