When writing test expectations for functions that throw, we need a bit careful.
For example, consider this simple test:
test('function throws', () {
expect(
someFunctionThatThrows(),
throwsStateError,
);
});
In this case, the test will fail, because someFunctionThatThrows()
is evaluated before the expect
function is called.
This is equivalent to writing the test like this:
test('function throws', () {
// if the function throws, the test will fail immediately
final result = someFunctionThatThrows();
// and this line will never be exectuted
expect(
result,
throwsStateError,
);
});
sponsor

Level up your Flutter app’s performance. Get full visibility into your Flutter app’s performance, including crashes, exceptions in Dart, network health, custom traces, and more. Solve your trickiest issues, optimize user journeys, and wow your end users - again and again.
To fix this, we can pass an anonymous function as an argument to the expect method:
test('function throws', () {
expect(
// function argument, will be evaluated *inside* the expect function
() => someFunctionThatThrows(),
throwsStateError,
);
});
Or even better, we can use a tear-off and pass someFunctionThatThrows
directly as an argument (without calling it):
test('function throws', () {
expect(
someFunctionThatThrows,
throwsStateError,
);
});
This is safer, and more concise too! 👌
For more info about tear-offs, see this rule about effective Dart usage.
Happy coding!