flutter-tester
Skill68 starsChanged 7 months agoMITView on GitHub
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.
3 other projects use a version of this, 2 of them edited.
Adopted by
Most recently taken up by
- Namma-Flutter/namma_wallettheir own version, first seen Oct 8, 2026
- FNOSP/fntv-client-multiplatformedited, first seen Oct 8, 2026
- FNOSP/FlyNarwhaledited, first seen Oct 8, 2026
Other versions3 projects use a version of this.
Word for word · 0
None found.
Edited · 2
- FNOSP/FlyNarwhal★ 51997% same
- FNOSP/fntv-client-multiplatform★ 51997% same
Wrote their own version · 1
- Namma-Flutter/namma_wallet★ 59same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository2 other files it gives its agents.
The file
We split this skill into the rules it gives an agent
4 rules. 2 are common, 0 are distinctive, and 2 are very specific to this project.
2
Common
Most of the 3 edited versions we read keep these.
0
Distinctive
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 15
Run dart run build_runner build to generate mocks after adding @GenerateMocks annotations
- Common: line 20
Test each architectural layer in isolation using Given-When-Then structure.
- Common: line 36
Test each layer against its own mocked dependencies:
- Very specific: line 85
Run dart run build_runner build after modifying @GenerateMocks.
“Common” is measured: kept by at least 6 in 10 of the 3 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Flutter Tester
Requirements
- Flutter project with
flutter_testdependency - Works with Riverpod, Mockito, and GetIt
- Run
dart run build_runner buildto generate mocks after adding@GenerateMocksannotations - Compatible with FVM (
fvm flutter testinstead offlutter 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
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
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
@GenerateMocks([IUserDAO, IUserAPI, ILogger])
void main() { ... }Run dart run build_runner build after modifying @GenerateMocks.
Register with GetIt
setUp(() {
mockDAO = MockIUserDAO();
mockLogger = MockILogger();
GetIt.I
..registerSingleton<IUserDAO>(mockDAO)
..registerSingleton<ILogger>(mockLogger);
});
tearDown(() => GetIt.I.reset()); // Critical — always resetFakes vs Mocks
- Fakes (
class FakeLogger extends ILogger) — silent stubs; use when you don't need to verify calls - Mocks (
MockILogger) — use when you needwhen(),verify(), orthenThrow()
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
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 ManagerCommon 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()intearDown- 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()orverifyNever()where appropriate- Tests are isolated and deterministic
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

