dart-matcher-best-practices
Best practices for using `expect` and `package:matcher`. Focuses on readable assertions, proper matcher selection, and avoiding common pitfalls.
Packaged view
This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.
Install command
npx @skill-hub/cli install kevmoo-dash-skills-dart-matcher-best-practices
Repository
Skill path: .agent/skills/dart-matcher-best-practices
Best practices for using `expect` and `package:matcher`. Focuses on readable assertions, proper matcher selection, and avoiding common pitfalls.
Open repositoryBest for
Primary workflow: Ship Full Stack.
Technical facets: Full Stack.
Target audience: everyone.
License: Apache-2.0.
Original source
Catalog source: SkillHub Club.
Repository owner: kevmoo.
This is still a mirrored public skill entry. Review the repository before installing into production workflows.
What it helps with
- Install dart-matcher-best-practices into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
- Review https://github.com/kevmoo/dash_skills before adding dart-matcher-best-practices to shared team environments
- Use dart-matcher-best-practices for development workflows
Works across
Favorites: 0.
Sub-skills: 0.
Aggregator: No.
Original source / Raw SKILL.md
---
name: dart-matcher-best-practices
description: |-
Best practices for using `expect` and `package:matcher`.
Focuses on readable assertions, proper matcher selection, and avoiding common pitfalls.
license: Apache-2.0
---
# Dart Matcher Best Practices
## When to use this skill
Use this skill when:
- Writing assertions using `expect` and `package:matcher`.
- Migrating legacy manual checks to cleaner matchers.
- Debugging confusing test failures.
## Core Matchers
### 1. Collections (`hasLength`, `contains`, `isEmpty`)
- **`hasLength(n)`**:
- Prefer `expect(list, hasLength(n))` over `expect(list.length, n)`.
- Gives better error messages on failure (shows actual list content).
- **`isEmpty` / `isNotEmpty`**:
- Prefer `expect(list, isEmpty)` over `expect(list.isEmpty, true)`.
- Prefer `expect(list, isNotEmpty)` over `expect(list.isNotEmpty, true)`.
- **`contains(item)`**:
- Verify existence without manual iteration.
- **`unorderedEquals(items)`**:
- Verify contents regardless of order.
### 2. Type Checks (`isA<T>` and `TypeMatcher<T>`)
- **`isA<T>()`**:
- Prefer for inline assertions: `expect(obj, isA<Type>())`.
- More concise and readable than `TypeMatcher<Type>()`.
- Allows chaining constraints using `.having()`.
- **`TypeMatcher<T>`**:
- Prefer when defining top-level reusable matchers.
- **Use `const`**: `const isMyType = TypeMatcher<MyType>();`
- Chaining `.having()` works here too, but the resulting matcher is not `const`.
### 3. Object Properties (`having`)
Use `.having()` on `isA<T>()` or other TypeMatchers to check properties.
- **Descriptive Names**: Use meaningful parameter names in the closure (e.g.,
`(e) => e.message`) instead of generic ones like `p0` to improve readability.
```dart
expect(person, isA<Person>()
.having((p) => p.name, 'name', 'Alice')
.having((p) => p.age, 'age', greaterThan(18)));
```
This provides detailed failure messages indicating exactly which property
failed.
### 4. Async Assertions
- **`completion(matcher)`**:
- Wait for a future to complete and check its value.
- **Prefer `await expectLater(...)`** to ensure the future completes before
the test continues.
- `await expectLater(future, completion(equals(42)))`.
- **`throwsA(matcher)`**:
- Check that a future or function throws an exception.
- `await expectLater(future, throwsA(isA<StateError>()))`.
- `expect(() => function(), throwsA(isA<ArgumentError>()))` (synchronous
function throwing is fine with `expect`).
### 5. Using `expectLater`
Use `await expectLater(...)` when testing async behavior to ensure proper
sequencing.
```dart
// GOOD: Waits for future to complete before checking side effects
await expectLater(future, completion(equals(42)));
expect(sideEffectState, equals('done'));
// BAD: Side effect check might run before future completes
expect(future, completion(equals(42)));
expect(sideEffectState, equals('done')); // Race condition!
```
## Principles
1. **Readable Failures**: Choose matchers that produce clear error messages.
2. **Avoid Manual Logic**: Don't use `if` statements or `for` loops for
assertions; let matchers handle it.
3. **Specific Matchers**: Use the most specific matcher available (e.g.,
`containsPair` for maps instead of checking keys manually).