tezvyn:

Dart's `expect` and Matchers: Writing Better Tests

AI-drafted, machine-checkedSource: pub.devbeginner

Dart's `expect` and Matchers are a grammar for your tests, letting you define complex rules beyond simple equality. Use them to verify values, check for exceptions, and test async Futures/Streams.

WHY IT EXISTS Simple assertions like assert(a == b) are too limited for robust testing. Modern applications have complex states, error conditions, and asynchronous data flows. The matcher library was created to provide an expressive, readable, and extensible way to specify test expectations, especially for these complex cases.

THE MENTAL MODEL Think of expect(actual, matcher) as a declarative statement: "I expect this actual value to satisfy the rule defined by this matcher." Matchers are pre-built, composable rules that describe the expected outcome. Instead of writing procedural code to check a value, you declare the desired state, making tests easier to read and write.

HOW IT WORKS The expect() function takes two arguments: the actual value produced by your code, and the matcher. If you pass a plain value as the second argument, it's implicitly wrapped in an equals() matcher. The function runs the matcher's logic against the actual value. If it passes, the test continues. If it fails, it throws a TestFailure with a descriptive message. For asynchronous code, special matchers like completion() intelligently wait for the operation to finish before checking the result, preventing flaky tests.

WHEN TO USE IT Matchers are the standard for assertions in Dart and Flutter tests. Use them for three main scenarios: first, for simple value validation using matchers like equals(), contains(), or inInclusiveRange(); second, for verifying that code throws a specific error using throwsA() or throwsFormatException; and third, for testing asynchronous code, using completion() for Futures and emitsInOrder() for Streams.

WHEN NOT TO USE IT Matchers and expect are strictly for testing environments. Never use them in your production application code for control flow or error handling. expect() is designed to halt a test and report a failure, which is not desirable behavior in a live app. Use standard try-catch blocks, conditional logic, and state management for handling logic and errors in your app.

ONE CANONICAL EXAMPLE Testing a Future requires the completion() matcher to ensure the test waits for the Future to resolve. This example tests that a Future completes with the value 10.

expect(Future.value(10), completion(equals(10)));

Without completion(), the test would incorrectly compare the Future object itself to the number 10 and fail immediately.

Read the original → pub.dev

Get five bites like this every day.

Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.