Write unit tests for BenefitCalculatorBloc
epic-benefit-calculator-core-logic-task-007 — Write bloc_test unit tests for BenefitCalculatorBloc covering: successful config load → correct initial state, InputChanged → recalculated result emitted, ResetRequested → state cleared, ShareRequested → success state preserved, and repository fetch failure → error state emitted. Mock BenefitMultiplierConfigRepository and BenefitCalculationService using mocktail.
Acceptance Criteria
Technical Requirements
Execution Context
Tier 4 - 323 tasks
Can start after Tier 3 completes
Implementation Notes
Use mocktail's when().thenAnswer() pattern to stub async repository methods returning Future
Avoid using real timers — if the BLoC uses debounce on inputs, use FakeAsync from quiver or clock package. Ensure the BLoC is closed after each test to prevent stream leaks.
Testing Requirements
Unit tests only using bloc_test and mocktail. No integration or widget tests required for this task. Each BLoC event maps to at least one dedicated blocTest() call. Use setUp() to instantiate a fresh BLoC and close it in tearDown().
Verify both emitted states (intermediate loading state if applicable, final success/error state). Aim for 90%+ branch coverage of BenefitCalculatorBloc. Run with: flutter test test/bloc/benefit_calculator_bloc_test.dart.
The exact formulas for SROI social value (public health system cost offset) may not be agreed upon with the client organisations or Bufdir. If formulas are disputed post-implementation, the service and all downstream tests will need to be revised.
Mitigation & Contingency
Mitigation: Document the two formulas and their multiplier inputs explicitly in the BenefitCalculationService source file and obtain sign-off from the product owner before implementation begins. Store formula multipliers exclusively in the Supabase config table so adjustments require only a config update, not a code deployment.
Contingency: If formulas are revised after implementation, the pure-function architecture means changes are isolated to BenefitCalculationService. Update the service, adjust unit tests, and re-run the test suite. No UI components need modification.
The BLoC must handle the asynchronous config fetch from the multiplier repository during initialisation. Race conditions between the config loading state and the first InputChanged event could result in calculations running against null or stale multiplier values.
Mitigation & Contingency
Mitigation: Guard all InputChanged event handlers in the BLoC with a null check on the loaded config state. Emit BenefitCalculationLoading until config resolves. Write a BLoC test that fires InputChanged before config loads and asserts the state remains BenefitCalculationLoading.
Contingency: If race conditions surface in integration testing, add an explicit config-loaded flag and queue InputChanged events until the flag is set, draining the queue on config resolution.