flutter-tester
Use when creating, writing, fixing, or reviewing tests in a Flutter project. Covers unit tests, widget tests, integration tests, Riverpod provider testing, and Mockito mocking. Provides Given-When-Then patterns, layer isolation strategies, and test setup for GetIt, SharedPreferences, and FakeDatabase.
Works with
---
name: flutter-tester
description: Use when creating, writing, fixing, or reviewing tests in a Flutter project. Covers unit tests, widget tests, integration tests, Riverpod provider testing, and Mockito mocking. Provides Given-When-Then patterns, layer isolation strategies, and test setup for GetIt, SharedPreferences, and FakeDatabase.
license: MIT
---
# Flutter Tester
## Requirements
- Flutter project with `flutter_test` dependency
- Works with Riverpod, Mockito, and GetIt
- Run `dart run build_runner build` to generate mocks after adding `@GenerateMocks` annotations
- Compatible with FVM (`fvm flutter test` instead of `flutter test`)
## Overview
Test each architectural layer in isolation using Given-When-Then structure. Always test both success and error paths. Never mock providers — override their dependencies instead.
## Reference Files
Load the relevant file based on what you're testing:
| What you're testing | Reference file |
| --- | --- |
| Repository, DAO, Service logic | `references/layer_testing_patterns.md` |
| Widget UI, interactions, dialogs, navigation | `references/widget_testing_guide.md` |
| Riverpod provider state, mutations, lifecycle | `references/riverpod_testing_guide.md` |
## Core Principles
### 1. Layer Isolation
Test each layer against its own mocked dependencies:
| Layer | What to test | What to mock |
| --- | --- | --- |
| **Repository** | Data coordination between sources | DAOs, APIs, Logger |
| **DAO** | Database CRUD operations | Use real in-memory DB, mock Logger |
| **Provider** | State management and transitions | Services, Repositories |
| **Service** | Business logic and workflows | Repositories, Network clients |
| **Widget** | UI behaviour and interactions | Provider dependencies (via overrides) |
### 2. Given-When-Then Structure
```dart
test('Given valid data, When fetchUsers called, Then returns user list', () async {
// Arrange (Given)
when(mockDAO.fetchAll()).thenAnswer((_) async => expectedUsers);
// Act (When)
final result = await repository.fetchUsers();
// Assert (Then)
expect(result, equals(expectedUsers));
verify(mockDAO.fetchAll()).called(1);
});
```
### 3. Test Organisation
```dart
group('UserRepository', () {
group('fetchUsers', () {
setUp(() { /* init mocks, register with GetIt */ });
tearDown(() => GetIt.I.reset()); // Always reset GetIt
test('Given success ... When ... Then ...', () { });
test('Given error ... When ... Then ...', () { });
});
});
```
## Standard Test Setup
### Generate Mocks
```dart
@GenerateMocks([IUserDAO, IUserAPI, ILogger])
void main() { ... }
```
Run `dart run build_runner build` after modifying `@GenerateMocks`.
### Register with GetIt
```dart
setUp(() {
mockDAO = MockIUserDAO();
mockLogger = MockILogger();
GetIt.I
..registerSingleton<IUserDAO>(mockDAO)
..registerSingleton<ILogger>(mockLogger);
});
tearDown(() => GetIt.I.reset()); // Critical — always reset
```
### Fakes vs Mocks
- **Fakes** (`class FakeLogger extends ILogger`) — silent stubs; use when you don't need to verify calls
- **Mocks** (`MockILogger`) — use when you need `when()`, `verify()`, or `thenThrow()`
## Quick Reference
| Scenario | Key pattern |
| --- | --- |
| Test a repository | Mock DAO + API → inject into repository constructor |
| Test a DAO | `FakeDatabase` or `openInMemoryDatabase()` in setUp, delete table in tearDown |
| Test a Riverpod provider | `createContainer(overrides: [serviceProvider.overrideWith(...)])` |
| Test a widget | Set screen size, use `find.byKey()`, call `pumpAndSettle()` |
| Test a loading state | Use `Completer`, `pump()` to assert loading, complete, `pump()` again |
| Test platform-specific UI | `debugDefaultTargetPlatformOverride = TargetPlatform.iOS` — reset after |
| Test GoRouter navigation | `FakeGoRouter` + `MockGoRouterProvider` |
## Running Tests
```bash
flutter test --coverage # All tests with coverage
flutter test test/path/to/test.dart # Specific file
flutter test --plain-name "Given valid data" # Filter by name
genhtml coverage/lcov.info -o coverage/html # Generate HTML coverage report
# Prefix any command with `fvm` if using Flutter Version Manager
```
## Common Mistakes
| Mistake | Fix |
| --- | --- |
| Mocking a provider directly | Override its dependencies: `provider.overrideWith(...)` |
| Missing `GetIt.I.reset()` in `tearDown` | Tests pollute each other — always reset |
| `await Future.delayed()` in tests | Use `await tester.pumpAndSettle()` or `Completer` instead |
| Finding widgets by text string | Use `find.byKey(const Key('name'))` — stable across text changes |
| No screen size in widget tests | Add `tester.view.physicalSize = const Size(1000, 1000)` |
| Not resetting `debugDefaultTargetPlatformOverride` | Set to `null` at the end of the test |
| `tearDown()` without a lambda | Write `tearDown(() async { ... })` not `tearDown() async { ... }` |
## Test Checklist
**Setup & Mocking:**
- [ ] Dependencies mocked (not providers)
- [ ] SharedPreferences mocked if used
- [ ] `GetIt.I.reset()` in `tearDown`
- [ ] Streams closed in `tearDown`
- [ ] Controllers disposed in `tearDown`
**Widget Tests:**
- [ ] Keys added to source widgets and used in `find.byKey()`
- [ ] Screen size set (`physicalSize` + `devicePixelRatio`)
- [ ] Platform overrides reset (`debugDefaultTargetPlatformOverride = null`)
- [ ] Navigation verified if applicable
**Test Coverage:**
- [ ] Success and failure paths covered
- [ ] Edge cases tested (null, empty, max values)
- [ ] Loading and error states tested
- [ ] Async handled correctly (no `Future.delayed`)
**Code Quality:**
- [ ] Given-When-Then naming used
- [ ] `verify()` or `verifyNever()` where appropriate
- [ ] Tests are isolated and deterministicMore Mobile skills
animation-vocabulary
emilkowalski/skills
Reverse-lookup glossary that turns a vague description of a web animation or motion effect into its exact term ("the bouncy thing when a popover opens" → Pop in; "the iOS rubber-band scroll" → Rubber-banding). Use when the user asks "what's it called when…", or describes a motion effect without knowing its name and wants the right word to prompt an AI or designer with. For naming an effect, not designing or building one.
xcode-project-setup
firebase/agent-skills
Safely modifies Xcode projects (.pbxproj) to add Swift Packages and link files. Use this skill whenever an iOS project needs dependencies installed (e.g. Firebase, Alamofire).
cross-border-ecommerce
nexscope-ai/ecommerce-skills
Cross-border e-commerce expansion advisor. Scores target markets on 8 weighted dimensions (market size, ecommerce penetration, competition, regulatory complexity, logistics infrastructure, payment ecosystem, cultural distance, IP protection), compares 5 fulfillment models with cost and transit data, provides country-by-country tax/duty compliance guides (EU VAT/IOSS, UK VAT, US sales tax, CA GST, AU GST, JP consumption tax), maps local payment preferences by market, and builds a phased expansion roadmap. No API key required.

