Claude
Skills
Sign in
Back

dart-add-unit-test

Included with Lifetime
$97 forever

Write unit tests with mocking and coverage analysis for pure Dart projects and CLI apps. Use when testing business logic, generating mocks with Mockito or mocktail, or measuring test coverage.

Code Review

What this skill does

# Dart Testing Suite

## Contents
- [Unit Testing](#unit-testing)
- [Mocking Dependencies](#mocking-dependencies)
- [Test Coverage](#test-coverage)
- [Workflow: Testing Execution](#workflow-testing-execution)

## Unit Testing
Utilize `package:test` as the standard testing library for Dart CLI and backend applications.
* Organize test files to mirror the `lib` directory structure. Append `_test.dart` to test files.
* Group related tests using the `group()` function.
* Use `setUp()` and `tearDown()` for shared test state.
* Write pure logic inside Domain/BLoC and extract to static pure functions for 100% unit test coverage.
* Use string interpolation for test group names: `group('$ClassName', ...)`
* Structure each test using the **Arrange-Act-Assert** (Given-When-Then) convention:
  - **Arrange**: Set up mocks, create instances, prepare input data.
  - **Act**: Call the method under test.
  - **Assert**: Verify the output or side effects.
* Separate setup from verification to keep tests readable and maintainable.

## Mocking Dependencies

### mocktail vs mockito Decision

| Criteria | `mocktail` (Recommended) | `mockito` |
|---|---|---|
| **Code generation** | Not needed | Requires `build_runner` |
| **Setup speed** | Fast (extend `Mock`) | Slower (annotation + codegen) |
| **Null safety** | Full support | Full support |
| **API style** | `when(() => mock.method())` | `when(mock.method())` |
| **Best for** | Most projects, fast iteration | Large projects with complex APIs |

**Rule**: Default to `mocktail` (no codegen, faster setup). Use `mockito` only when you need `@GenerateNiceMocks` for complex APIs with many overloads.

### mocktail Setup (Recommended)
```dart
import 'package:mocktail/mocktail.dart';

// Create mock — no code generation needed
class MockUserRepository extends Mock implements UserRepository {}

void main() {
  late MockUserRepository mockRepo;

  setUp(() {
    mockRepo = MockUserRepository();
  });

  test('fetches user successfully', () {
    // Arrange
    when(() => mockRepo.getUser('1'))
        .thenAnswer((_) async => const User(id: '1', name: 'Alice'));

    // Act
    final user = await mockRepo.getUser('1');

    // Assert
    expect(user.name, 'Alice');
    verify(() => mockRepo.getUser('1')).called(1);
  });
}
```

### mockito Setup (Code-Gen)
```dart
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';

@GenerateNiceMocks([MockSpec<UserRepository>()])
import 'user_test.mocks.dart';  // Generated by: dart run build_runner build
```

### Verification APIs

| API | Purpose |
|---|---|
| `verify(() => mock.method()).called(1)` | Assert method was called exactly once |
| `verifyNever(() => mock.method())` | Assert method was never called |
| `verifyNoMoreInteractions(mock)` | Assert no unchecked interactions remain |
| `verifyInOrder([...])` | Assert methods were called in specific order |
| `reset(mock)` | Clear all stubs and interactions |

### Registering Fallback Values
For methods with custom types as parameters:
```dart
setUpAll(() {
  registerFallbackValue(const User(id: '0', name: 'fallback'));
});
```

## Test Coverage
* Target 100% logic coverage for domain models and business logic.
* Run coverage with `dart test --coverage=coverage` or `flutter test --coverage`.
* See `dart-coverage` skill for detailed LCOV/HTML report generation.

## Workflow: Testing Execution
Follow this sequential workflow when testing a Dart feature. Copy the checklist to track progress.

### Task Progress
- [ ] **Step 1: Write Unit Tests.** Focus on core business logic. Ensure files end with `_test.dart`.
- [ ] **Step 2: Generate Mocks.** Run `dart run build_runner build` to generate mocks if using Mockito.
- [ ] **Step 3: Run Tests.** Execute `dart test`.
- [ ] **Step 4: Check Coverage.** Run `dart test --coverage=coverage` and verify coverage targets are met.

Related in Code Review