Reputation: 31
I wrote a simple provider in flutter that should provide the current date/time (clock.now() is from the clock package):
final clockProvider = StateNotifierProvider<Clock, DateTime>((ref) {
return Clock();
});
class Clock extends StateNotifier<DateTime> {
late final Timer _timer;
Clock() : super(clock.now()) {
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
state = clock.now();
});
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
}
One reason for that is that I thought it would be easier this way to test with a given set time using Mockito:
@GenerateNiceMocks([
MockSpec<Clock>(),
])
void main() {
testWidgets(
"test clock", (tester) async {
// arrange
final MockClock mockClock = MockClock();
when(mockClock.state).thenReturn(DateTime(2000));
final container = ProviderContainer(
overrides: [
clockProvider.overrideWithValue(mockClock),
],
);
await container.pump();
final result = container.read(clockProvider);
});
This throws the following exception:
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following ProviderException was thrown running a test:
An exception was thrown while building StateNotifierProvider<Clock, DateTime>#0cdfd.
Thrown exception:
Bad state: Tried to read the state of an uninitialized provider
When following this approach and overwriting not with a value but with a provider the error message is the same and flutter still complains about "Tried to read the state of an uninitialized provider":
final MockClock mockClock = MockClock();
when(mockClock.state).thenReturn(DateTime(2000));
final mockClockProvider = StateNotifierProvider<Clock, DateTime>((ref) {
return mockClock;
});
final container = ProviderContainer(
overrides: [
clockProvider.overrideWithProvider(mockClockProvider),
],
);
Would appreciate any help in finding the mistake!
Upvotes: 0
Views: 706
Reputation: 68
If you want to test with a given time, the approach you linked basically does this by providing arguments for your constructor. In your case it would be something like
class ClockNotifier extends StateNotifier<DateTime> {
late final Timer _timer;
ClockNotifier(Clock clock = clock.now()) : super(clock) {
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
state = clock.now();
});
}
Note: Doing state = clock.now();
in the Timer.periodic()
would override everything you set in the constructor. But it might not effect it for your test.
Second note: you should rename it to ClockNotifier as you are using the Clock package
I hope that helps, I am doing Flutter only since a few month now.
Upvotes: 0