testing
Writes unit and widget tests for blocs, repositories, and screens using bloc_test + mocktail
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Writes unit and widget tests for blocs, repositories, and screens using bloc_test + mocktail
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
Handles cross-feature BusEvent communication with EventBusManager in the Flutter base template
Implements BLoC state management using AppBlocBase, an abstract State hierarchy, and a freezed _StateData
Builds the data layer with Freezed DTOs, Retrofit clients, hive_ce local stores, and repositories wired through injectable
Reviews UI-layer changes — screens, blocs, widgets, routes — against the template's StateBase + AppBlocBase + fl_theme conventions
Adds and updates app strings through the CSV → ARB → generated localizations workflow
Scaffolds a new feature module under apps/main/lib/presentation/modules using the bundled module generator
استنادا إلى تصنيف SOC المهني
| name | testing |
| description | Writes unit and widget tests for blocs, repositories, and screens using bloc_test + mocktail |
| license | MIT |
| compatibility | all |
| metadata | {"audience":"flutter-developers","framework":"flutter","pattern":"testing"} |
Tests live next to the package they cover:
apps/main/test/ # app-level tests
core/test/ # core-level tests
modules/data_source/test/
plugins/<plugin>/test/
A common shape inside apps/main/test/:
test/
├── unit/
│ ├── bloc/
│ ├── domain/
│ └── data/
├── widget/
└── helpers/
flutter test # current package
flutter test test/unit/bloc/foo_bloc_test.dart
make coverage_main # coverage on apps/main, via coverage.sh
There is no make test / make analyze aggregate target — invoke flutter test and flutter analyze (or dart analyze) per package as needed.
Use bloc_test for sequence assertions and mocktail for collaborators.
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
class _MockUsecase extends Mock implements FeatureUsecase {}
void main() {
late _MockUsecase usecase;
late FeatureBloc bloc;
setUp(() {
usecase = _MockUsecase();
bloc = FeatureBloc(null, usecase);
});
tearDown(() => bloc.close());
group('FeatureBloc', () {
test('initial state is FeatureInitial with empty data', () {
expect(bloc.state, isA<FeatureInitial>());
expect(bloc.state.data.detail, isNull);
});
blocTest<FeatureBloc, FeatureState>(
'GetFeatureEvent loads detail and stays in FeatureInitial',
build: () {
when(() => usecase.getById('1'))
.thenAnswer((_) async => Item(id: '1', name: 'A'));
return bloc;
},
act: (b) => b.add(GetFeatureEvent('1')),
expect: () => [
isA<FeatureInitial>().having((s) => s.detail?.id, 'detail.id', '1'),
],
);
});
}
Note: this template's blocs use abstract class state hierarchies, not freezed unions, so assert with isA<FeatureInitial>() plus having(...) rather than equality on a sealed union.
class _MockApi extends Mock implements UserApiClient {}
void main() {
late _MockApi api;
late UserRepositoryImpl repo;
setUp(() {
api = _MockApi();
repo = UserRepositoryImpl(api);
});
test('getUser delegates to api client', () async {
final user = UserModel(id: '1', name: 'A');
when(() => api.getUser('1')).thenAnswer((_) async => user);
expect(await repo.getUser('1'), user);
verify(() => api.getUser('1')).called(1);
});
}
Wrap the screen in the same providers it gets in production: a BlocProvider (with a mocked bloc) and MaterialApp.router or a plain MaterialApp with Localizations if your widget reads context.l10n.
class _MockBloc extends MockBloc<FeatureEvent, FeatureState>
implements FeatureBloc {}
void main() {
late _MockBloc bloc;
setUp(() => bloc = _MockBloc());
Widget pump(Widget child) => MaterialApp(
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: BlocProvider<FeatureBloc>.value(value: bloc, child: child),
);
testWidgets('shows empty state when items is empty', (tester) async {
when(() => bloc.state).thenReturn(
FeatureInitial(data: const _StateData()),
);
await tester.pumpWidget(pump(const FeatureScreen()));
expect(find.byType(EmptyData), findsOneWidget);
});
}
For interactions, drive a real bloc through the actions extension instead of mocking — it catches more bugs.
Fallback values for any value-typed argument matchers (registerFallbackValue(...)).verifyNever/verifyInOrder over loose verify.Mock instances between tests — recreate in setUp.lib/.../foo_bloc.dart ↔ test/unit/bloc/foo_bloc_test.dart).tearDown.mocktail consistently across the file.flutter test passes locally before commit.state == FeatureLoaded(...) — equality is reference-based on these abstract state classes; use isA<>().having(...).registerFallbackValue for typed arguments and getting cryptic mocktail errors.MaterialApp ancestor; localizations and themes blow up.