How do you unittest exceptions in Dart?

Dart

Dart Problem Overview


Consider a function that does some exception handling based on the arguments passed:

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

How do I test that the right kind of exception is raised?

Dart Solutions


Solution 1 - Dart

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).

Solution 2 - 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");  
});

Solution 3 - Dart

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.
    ),
  ),
);

Solution 4 - Dart

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>()));
}); 

Solution 5 - Dart

While the other answers are definitely valid, APIs like TypeMatcher<Type>() are deprecated now, and you have to use isA<TypeOfException>().

For instance, what was previously,

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

Will now be

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

Solution 6 - Dart

For simple exception testing, I prefer to use the static method API:

Expect.throws(
  // test condition
  (){ 
    throw new Exception('code I expect to throw');
  },
  // exception object inspection
  (err) => err is Exception
);

Solution 7 - Dart

I used the following approach:

First you need to pass in your method as a lambda into the expect function:

expect(() => method(...), ...)

Secondly you need to use throwsA in combination with isInstanceOf.

throwsA makes sure that an exception is thrown, and with isInstanceOf you can check if the correct Exception was thrown.

Example for my unit test:

expect(() => parser.parse(raw), throwsA(isInstanceOf<FailedCRCCheck>()));

Hope this helps.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionShailen TuliView Question on Stackoverflow
Solution 1 - DartShailen TuliView Answer on Stackoverflow
Solution 2 - DartShannon -jj BehrensView Answer on Stackoverflow
Solution 3 - DartHugo PassosView Answer on Stackoverflow
Solution 4 - DartattdonaView Answer on Stackoverflow
Solution 5 - DartDinanjananView Answer on Stackoverflow
Solution 6 - DartJohn EvansView Answer on Stackoverflow
Solution 7 - DartLostSoulView Answer on Stackoverflow