dart-generate-test-mocks — Claude Code skill: mocks for Dart tests
A Dart testing skill: the agent injects external services through constructors, generates mock classes with mockito and build_runner, then writes the unit test.
npx skills add dart-lang/skills --skill dart-generate-test-mocks -a claude-codeWhat dart-generate-test-mocks does
This skill walks the agent through mocked unit tests in Dart. First the class under test gets reshaped for substitution: http.Client and similar services go in through the constructor, URLs travel as Uri objects. Test and codegen packages come from dart pub add dev:test dev:mockito dev:build_runner.
Then a test file gets @GenerateNiceMocks([MockSpec<http.Client>()]), imports the generated .mocks.dart, and dart run build_runner build writes the mock classes. For anything returning a Future or Stream the skill insists on thenAnswer rather than thenReturn. It also skips @GenerateMocks in favour of nice mocks, since an unstubbed method would otherwise throw.
A ten-step checklist runs alongside a failure loop: an ArgumentError from an async stub, an import name that does not match the .mocks.dart file, build errors. You need the Dart SDK and the pub packages — skip build_runner and the mock classes never appear, so the test will not compile.
What it helps with
- Mock
http.Clientinside a service unit test - Generate mock classes with
build_runner - Stub a method that returns a
Future - Check that a mock method ran exactly once
- Track down an
ArgumentErrorfrom an async stub
Example prompts for the agent
- Generate mocks for `ApiService` with `@GenerateNiceMocks` and run `dart run build_runner build`
- Write a unit test for `fetchData`: mock `http.Client` and verify the call
- The test throws `ArgumentError` — rewrite that async stub with `thenAnswer`
How to install dart-generate-test-mocks
1Skills CLI (Vercel)
npx skills add dart-lang/skills --skill dart-generate-test-mocks -a claude-code2Manually: put the files in place
~/.claude/skills/dart-generate-test-mocks/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/dart-generate-test-mocks/
1Skills CLI (Vercel)
npx skills add dart-lang/skills --skill dart-generate-test-mocks -a codex2Manually: put the files in place
.agents/skills/dart-generate-test-mocks/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add dart-lang/skills --skill dart-generate-test-mocks -a cursor2Manually: put the files in place
.cursor/skills/dart-generate-test-mocks/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install dart-lang/skills dart-generate-test-mocks2Manually: put the files in place
.github/skills/dart-generate-test-mocks/SKILL.md1Skills CLI (Vercel)
npx skills add dart-lang/skills --skill dart-generate-test-mocks -a gemini-cli2Platform CLI
gemini skills install https://github.com/dart-lang/skills --path skills/dart-generate-test-mocksManually: put the files in place
.devin/skills/dart-generate-test-mocks/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add dart-lang/skills --skill dart-generate-test-mocks -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set7
The whole set →Similar
Questions about dart-generate-test-mocks
How do I install dart-generate-test-mocks in Claude Code?
Run npx skills add dart-lang/skills --skill dart-generate-test-mocks -a claude-code. The skill lands at ~/.claude/skills/dart-generate-test-mocks/SKILL.md.
What does dart-generate-test-mocks do?
It guides the agent from dependency injection in the class to package setup, mock generation and a finished test with stubs and call verification.
Why nice mocks instead of `@GenerateMocks`?
Nice mocks hand back empty values when a method has no stub, so the test fails on your assertion rather than on a missing-stub exception.
Source text
SKILL.md · BSD-3-Clause
---
name: dart-generate-test-mocks
description: Define and generate mock objects for external dependencies using `package:mockito` and `build_runner`. Use when unit testing classes that depend on complex external services like APIs or databases.
metadata:
model: models/gemini-3.1-pro-preview
last_modified: Fri, 24 Apr 2026 15:13:58 GMT
---
# Testing and Mocking Dart Applications
## Contents
- [Structuring Code for Testability](#structuring-code-for-testability)
- [Managing Dependencies](#managing-dependencies)
- [Generating Mocks](#generating-mocks)
- [Implementing Unit Tests](#implementing-unit-tests)
- [Workflow: Creating and Running Mocked Tests](#workflow-creating-and-running-mocked-tests)
- [Examples](#examples)
## Structuring Code for Testability
Design Dart classes to support dependency injection. Isolate complex external dependencies (like API clients or databases) so they can be replaced with mock objects during testing.
- Inject external services (e.g., `http.Client`) through class constructors.
- Represent URLs strictly as `Uri` objects using `Uri.parse(string)`.
- Utilize Dart's object-oriented features (classes, mixins) to define clear interfaces for external interactions.
## Managing Dependencies
Configure the `pubspec.yaml` file with the necessary testing and code generation packages.
- Add runtime dependencies (e.g., `package:http`) using `dart pub add http`.
- Add testing dependencies using `dart pub add dev:test dev:mockito dev:build_runner`.
- Import HTTP libraries with a prefix to avoid namespace collisions: `import 'package:http/http.dart' as http;`.
## Generating Mocks
Use `package:mockito` and `build_runner` to automatically generate mock classes for fixed scenarios and behavior verification.
- Always use the `@GenerateNiceMocks` annotation (preferable to `@GenerateMocks` to avoid missing stub exceptions).
- Place the annotation in the test file, passing a list of `MockSpec<Type>()` objects.
- Import the generated file using the `.mocks.dart` extension.
- Execute `build_runner` to generate the mock files: `dart run build_runner build`.
## Implementing Unit Tests
Isolate the system under test using the generated mock objects. Use `package:test` to structure the test suite.
- **Stubbing:** Configure mock behavior before interacting with the system under test.
- Use `when(mock.method()).thenReturn(value)` for synchronous methods.
- **CRITICAL:** Always use `thenAnswer((_) async => value)` for methods returning a `Future` or `Stream`. Never use `thenReturn` for asynchronous returns.
- **Verification:** Assert that the system under test interacted with the mock object correctly.
- Use `verify(mock.method()).called(1)` to check exact invocation counts.
- Use argument matchers like `any`, `anyNamed`, or `captureAny` for flexible verification.
## Workflow: Creating and Running Mocked Tests
Use the following checklist to implement and verify mocked unit tests.
### Task Progress
- [ ] 1. Identify the external dependency to mock (e.g., `http.Client`).
- [ ] 2. Inject the dependency into the target class constructor.
- [ ] 3. Create a test file (e.g., `target_test.dart`) and add `@GenerateNiceMocks([MockSpec<Dependency>()])`.
- [ ] 4. Add the `part` or `import` directive for the generated `.mocks.dart` file.
- [ ] 5. Run `dart run build_runner build` to generate the mock classes.
- [ ] 6. Write the test cases using `group()` and `test()`.
- [ ] 7. Stub required behaviors using `when()`.
- [ ] 8. Execute the target method.
- [ ] 9. Verify interactions using `verify()` and assert outcomes using `expect()`.
- [ ] 10. Run the test suite using `dart test`.
### Feedback Loop: Test Failures
If tests fail or `build_runner` encounters errors:
1. **Run validator:** Execute `dart test` or `dart run build_runner build`.
2. **Review errors:** Check for missing stubs, mismatched argument matchers, or syntax errors in the generated files.
3. **Fix:**
- If a mock method throws an unexpected null error, ensure you used `@GenerateNiceMocks`.
- If an async stub throws an `ArgumentError`, change `thenReturn` to `thenAnswer`.
- If `build_runner` fails, ensure the `.mocks.dart` import matches the file name exactly.
4. Repeat until all tests pass.
## Examples
### High-Fidelity Mocking and Testing Example
**1. System Under Test (`lib/api_service.dart`)**
```dart
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiService {
final http.Client client;
ApiService(this.client);
Future<String> fetchData(String urlString) async {
final uri = Uri.parse(urlString);
final response = await client.get(uri);
if (response.statusCode == 200) {
return jsonDecode(response.body)['data'];
} else {
throw Exception('Failed to load data');
}
}
}
```
**2. Test Implementation (`test/api_service_test.dart`)**
```dart
import 'package:test/test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'package:http/http.dart' as http;
import 'package:my_app/api_service.dart';
// Generate the mock class for http.Client
@GenerateNiceMocks([MockSpec<http.Client>()])
import 'api_service_test.mocks.dart';
void main() {
group('ApiService', () {
late ApiService apiService;
late MockClient mockHttpClient;
setUp(() {
mockHttpClient = MockClient();
apiService = ApiService(mockHttpClient);
});
test('returns data if the http call completes successfully', () async {
// Arrange: Stub the async HTTP GET request using thenAnswer
when(mockHttpClient.get(any)).thenAnswer(
(_) async => http.Response('{"data": "Success"}', 200),
);
// Act
final result = await apiService.fetchData('https://api.example.com/data');
// Assert
expect(result, 'Success');
// Verify the mock was called with the correct Uri
verify(mockHttpClient.get(Uri.parse('https://api.example.com/data'))).called(1);
});
test('throws an exception if the http call completes with an error', () {
// Arrange
when(mockHttpClient.get(any)).thenAnswer(
(_) async => http.Response('Not Found', 404),
);
// Act & Assert
expect(
apiService.fetchData('https://api.example.com/data'),
throwsException,
);
});
});
}
```
© dart-lang · BSD-3-Clause · dart-lang/skills