use-test-throws-matchers

Same as use_test_throws_matchers in Dart lints

Group
Style
Path
lint/style/use-test-throws-matchers
Default
On (recommended)
Origin
Dart lints
Rule
508 of 512
recommended

Prefers throwsA matchers over try { ...; fail(...); } catch (...) {}.

A try statement with a single catch clause, no finally, and a body that ends in a call to the test framework's fail hand-rolls what expect(() => ..., throwsA(...)) states directly, and with worse failure messages. Like the official rule, only the top-level fail declared in package:test_api/src/frontend/expect.dart counts. Current test_api releases no longer declare it there (package:test, test_api, and flutter_test re-export package:matcher's fail), so only code using such an old test_api is reported; a local or member function named fail never is. The declaring library is identified through the package configuration, including when test_api is a dependency.

try {
  parse('');
  fail('Expected a FormatException');  // BAD
} on FormatException {}

expect(() => parse(''), throwsA(isA<FormatException>())); // GOOD

Invalid

lib/bad_frontend_fail.dartdart
import 'src/frontend/expect.dart';
import 'src/frontend/expect.dart' as expectations;

int parse(String input) => int.parse(input);

void throwsOnEmptyInput() {
  try {
    parse('');
    fail('Expected a FormatException');
  } on FormatException {}
}

void catchAll() {
  try {
    parse('x');
    expectations.fail('no throw');
  } catch (e) {
    print(e);
  }
}

void twoCatchClauses() {
  try {
    parse('');
    fail('no throw');
  } on FormatException {
    // expected
  } on ArgumentError {
    // also fine
  }
}

void localFailShadows() {
  void fail(String message) => print(message);
  try {
    parse('');
    fail('no throw');
  } catch (_) {}
}
lib/bad_frontend_fail.dartUse the `throwsA` matcher instead of using `fail` when there is no exception thrown.
8 parse('');
9 fail('Expected a FormatException');
lib/bad_frontend_fail.dartUse the `throwsA` matcher instead of using `fail` when there is no exception thrown.
15 parse('x');
16 expectations.fail('no throw');

Valid

example.dartdart
import 'package:test/test.dart';

int parse(String input) => int.parse(input);

void main() {
  test('uses throwsA', () {
    expect(() => parse(''), throwsA(isA<FormatException>()));
  });

  test('two catch clauses', () {
    try {
      parse('');
      fail('no throw');
    } on FormatException {
      // expected
    } on ArgumentError {
      // also fine
    }
  });

  test('has finally', () {
    try {
      parse('');
      fail('no throw');
    } catch (_) {
    } finally {
      print('done');
    }
  });

  test('fail is not last', () {
    try {
      fail('no throw');
      parse('');
    } catch (_) {}
  });

  test('local fail shadows the matcher', () {
    void fail(String message) => print(message);
    try {
      parse('');
      fail('no throw');
    } catch (_) {}
  });

  test('try/finally only', () {
    try {
      parse('');
    } finally {
      print('done');
    }
  });
}

Configure use-test-throws-matchers

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "use-test-throws-matchers": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/use-test-throws-matchers: <reason>