Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you unittest exceptions in Dart?

Tags:

dart

People also ask

How do you throw an exception in Dart?

The try / on / catch BlocksThe on block is used when the exception type needs to be specified. The catch block is used when the handler needs the exception object. The try block must be followed by either exactly one on / catch block or one finally block (or one of both).

What is exception handling in Dart?

An exception is an error occurred at runtime because Dart runtime could not execute a statement successfully or any other thousand reasons. An exception is an error occurred at runtime because Dart runtime could not execute a statement successfully or any other thousand reasons.

How do you handle throw exception in flutter?

Handling Exceptions in Flutter The try block contains the code that might possibly throw an exception. The try block must be followed by on or catch blocks, and an optional finally block. The catch block is used to catch and handle any exceptions thrown in the try block.


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


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

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

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

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