Files

61 lines
1.7 KiB
Cheetah

---
description: "BLoC testing conventions for {{PROJECT_NAME}}"
alwaysApply: false
---
# BLoC Testing Standards — {{PROJECT_NAME}}
## Test pattern (bloc_test)
```dart
// {{TEST_PATTERN}}
void main() {
late AuthBloc authBloc;
late MockAuthRepository mockRepo;
setUp(() {
mockRepo = MockAuthRepository();
authBloc = AuthBloc(repository: mockRepo);
});
tearDown(() => authBloc.close());
group('AuthBloc', () {
blocTest<AuthBloc, AuthState>(
'emits [Loading, Authenticated] when login succeeds',
build: () {
when(() => mockRepo.login(any(), any()))
.thenAnswer((_) async => const Right(User(id: '1', email: 'test@test.com')));
return authBloc;
},
act: (bloc) => bloc.add(const AuthLoginRequested(email: 'test@test.com', password: 'pass')),
expect: () => [
const AuthLoading(),
isA<AuthAuthenticated>(),
],
);
blocTest<AuthBloc, AuthState>(
'emits [Loading, Failure] when login fails',
build: () {
when(() => mockRepo.login(any(), any()))
.thenAnswer((_) async => const Left(AuthError('Invalid credentials')));
return authBloc;
},
act: (bloc) => bloc.add(const AuthLoginRequested(email: 'bad', password: 'bad')),
expect: () => [
const AuthLoading(),
const AuthFailure('Invalid credentials'),
],
);
});
}
```
## Rules
- Use `mocktail` for mocking — never `mockito`
- Every BLoC test file: `test/features/[feature]/[feature]_bloc_test.dart`
- Coverage requirement: all state transitions must be tested
- Use `Given/When/Then` naming in test descriptions
- Test error paths as thoroughly as success paths