harishwarrior/flutter-claude-skills4 files

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.

Specification
Skill ID
harishwarrior/flutter-claude-skills/flutter-tester
Publisher
harishwarrior
Repository
flutter-claude-skills
Installs
0
Files
4
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

harishwarrior/flutter-claude-skills/flutter-testerInstalls these files
  • SKILL.md
  • references/layer_testing_patterns.md
  • references/riverpod_testing_guide.md
  • references/widget_testing_guide.md

What this skill tells the agent

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 testingReference file
Repository, DAO, Service logicreferences/layer_testing_patterns.md
Widget UI, interactions, dialogs, navigationreferences/widget_testing_guide.md
Riverpod provider state, mutations, lifecyclereferences/riverpod_testing_guide.md

Core Principles

1. Layer Isolation

Test each layer against its own mocked dependencies:

LayerWhat to testWhat to mock
RepositoryData coordination between sourcesDAOs, APIs, Logger
DAODatabase CRUD operationsUse real in-memory DB, mock Logger
ProviderState management and transitionsServices, Repositories
ServiceBusiness logic and workflowsRepositories, Network clients
WidgetUI behaviour and interactionsProvider 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 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

ScenarioKey pattern
Test a repositoryMock DAO + API → inject into repository constructor
Test a DAOFakeDatabase or openInMemoryDatabase() in setUp, delete table in tearDown
Test a Riverpod providercreateContainer(overrides: [serviceProvider.overrideWith(...)])
Test a widgetSet screen size, use find.byKey(), call pumpAndSettle()
Test a loading stateUse Completer, pump() to assert loading, complete, pump() again
Test platform-specific UIdebugDefaultTargetPlatformOverride = TargetPlatform.iOS — reset after
Test GoRouter navigationFakeGoRouter + 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 Manager

Common Mistakes

MistakeFix
Mocking a provider directlyOverride its dependencies: provider.overrideWith(...)
Missing GetIt.I.reset() in tearDownTests pollute each other — always reset
await Future.delayed() in testsUse await tester.pumpAndSettle() or Completer instead
Finding widgets by text stringUse find.byKey(const Key('name')) — stable across text changes
No screen size in widget testsAdd tester.view.physicalSize = const Size(1000, 1000)
Not resetting debugDefaultTargetPlatformOverrideSet to null at the end of the test
tearDown() without a lambdaWrite 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 deterministic

Use this skill in a project

Open any RiverX project, search the Skills panel for harishwarrior/flutter-claude-skills/flutter-tester, and install it in one click.

Use this skill