Scaffolding
test_prereq Free
- Tier
- Freeversion 1.0.7
- Command
archipelago generate test_prereq- Generates
utilities/test_prereq
- Used by
- utilities_sdk, storage_sdk, package_info_provider, app_blackbox, app_debugger, app_debugger_network and 1 more
TestPrerequisitecontract for composition-root test-environment setup. Implemented by packages that perform real platform I/O (e.g.@preResolvegettersinjectableawaits inside$initGetIt) during DI init, soinitializeInjector()can run under plainflutter testwithout aMissingPluginException. Pure Dart, no Flutter dependency — you won't generate this directly; consuming bricks self-generate it.
Variables
| Variable | Type | Default | Description |
|---|---|---|---|
isForMonorepo | boolean | true | Whether this is being generated as part of a monorepo |
Install
Interactive
archipelago generate test_prereqNon-interactive (CI)
archipelago generate test_prereq --config my_config.jsonIn practice you rarely run this yourself: app_debugger and other infrastructure bricks self-generate test_prereq as a hard dependency (via SubBrickGenerator) the first time they need it, checking ArchipelagoConfigHelper.installedBricks().contains('test_prereq') first so it only runs once.
Generated Structure
utilities/
└── test_prereq/
└── lib/
├── test_prereq.dart
└── src/
└── test_prerequisite.dartA single pure-Dart package — no Flutter SDK dependency, so any package can depend on it at zero cost.
Public API
abstract interface class TestPrerequisite {
String get owner; // package name, for diagnostics
String get reason; // mirrors the declaring pubspec's `reason:` field
Future<void> install(); // idempotent — safe to call more than once
Future<void> uninstall() async {} // default no-op; override if reversible
}A consuming package implements this to install a platform-interface fake (or a mock initial value) that lets its real DI-init-time I/O succeed under test, without touching production behaviour. app_debugger's AppDebuggerTestPrerequisite (ships in app_debugger's own package, not here) is the reference implementation — it fakes PathProviderPlatform so PainterFlagsCubit/FabPositionCubit's @preResolve getTemporaryDirectory() calls don't throw under plain flutter test.
Invariants
- Idempotent —
install()may run more than once per test process (multiple test files,setUpAllper group) and must no-op after the first call. - No
GetItaccess — a prerequisite runs beforeinitializeInjector(); it must not read from or write to the container. - No
flutter_testimport — keeps it usable fromintegration_test/andflutter_test_config.dart, and keepsflutter_testout of a shipped package's dependency graph. - Binding-safe — may assume
TestWidgetsFlutterBinding.ensureInitialized()already ran; must not call it itself.
Declaring a Prerequisite
A package needs one when its DI init does platform I/O. That is a @preResolve that calls a plugin, a global module init() that eagerly resolves a plugin-backed type, or an eagerly built object whose constructor touches a plugin. In the Archipelago repository, CI runs scripts/check_di_test_prerequisites and fails when a package with a @preResolve and a plugin dependency has no declaration.
A package that needs one declares it under archipelago: in its own pubspec.yaml:
archipelago:
test_prerequisites:
- class: AppDebuggerTestPrerequisite
reason: >-
AppDebuggerRegisterModule's @preResolve cubits call path_provider
getTemporaryDirectory() during $initGetIt.When the package's brick is installed, its post_gen hook adds the prerequisite to the app's harness. It uses shared_hooks TestHarnessWriter, which ServiceLocatorUpdater.addExternalModule calls. After a hand edit, run dart run monorepo_toolkit generate test-harness (see monorepo_toolkit). Both write every declared prerequisite of the app's dependencies into test/support/composition_root_harness.dart, in resolved order, with each reason: as a comment. test/di/injector_test.dart calls installCompositionRootPrerequisites() from that file before initializeInjector(). Commit the harness. See Testing.
DI & Wiring
None — TestPrerequisite implementations are plain Dart classes assembled by the generator into a test harness, not registered in the runtime DI container (invariant 2 above forbids it).
Dependencies
Dev-only: test ^1.31.0, very_good_analysis. No runtime dependencies.
Platform Setup
None — pure Dart package.
Implementations
Concrete fakes live in the packages that implement TestPrerequisite, each declared in its own pubspec.yaml:
| Package (brick) | Class | Fakes |
|---|---|---|
app_debugger (page) | AppDebuggerTestPrerequisite | PathProviderPlatform |
package_info_provider (page) | PackageInfoProviderTestPrerequisite | PackageInfo.setMockInitialValues |
device_info_impl (page) | DeviceInfoTestPrerequisite | DeviceInfoPlatform (macOS and Linux hosts) |
storage_sdk_shared_preferences (page) | StorageSdkSharedPreferencesTestPrerequisite | SharedPreferencesAsyncPlatform (in memory) |
app_blackbox (page) | AppBlackboxTestPrerequisite | PathProviderPlatform |
app_debugger_network (page) | AppDebuggerNetworkTestPrerequisite | FlutterLocalNotificationsPlatform (Android) |
Several packages fake the same plugin (app_debugger and app_blackbox both fake path_provider). A plugin has one global platform instance, so the prerequisite that installs last wins. For that reason, a fake must answer every method that any package might call, not only the method its own package calls.
monitoring_impl was in the original list but needs none: it skips a vendor that fails to build, such as Crashlytics with no Firebase app (details).
Limitations
- Ships with the contract only, no concrete fakes (see Implementations).
utilities_sdk'sdevice_info_impldoes platform I/O in a@preResolvebut has no prerequisite yet. A generated app with device info fails its composition-root test until that is fixed.isForMonorepo: false(standalone) skips workspace registration entirely — there is no non-monorepo consumption path documented beyond that.
Changelog
Run archipelago brick info test_prereq to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.