Skip to content
DeveloperMemos

Testing FutureProviders in Flutter Unit Tests

Flutter, Unit Testing, Riverpod1 min read

Earlier this week, I was upgrading Riverpod in one of my Flutter projects and had to refactor some of my providers that broke.

While refactoring, I realized that I needed to test one of my new FutureProviders in a unit test, and I wasn't initially sure how to do it. Usually, when testing a Provider in a unit test, you do something like this:

1final container = await tester.pumpProviderScope(
2 overrides: _createOverrides(),
3);
4
5var viewModel = container.read(statsViewModelProvider);
6
7expect(viewModel.selectedDateRange, GraphDateRange.LAST_7_DAYS);
8expect(viewModel.selectionLabel.contains("7"), true);

The above code is directly pasted from one of my unit tests. The thing with a FutureProvider is that the value is async and determined at a later date, or it has loading states. So just calling container.read on it won't give you a direct value.

What to do for FutureProviders?

It turns out that you can actually access the future value of the FutureProvider and await it, which forces the unit test to execute the operation inside the FutureProvider:

1final value = await container.read(myProvider.future);

So here's what I ended up using for my unit test to get things working again (it's abbreviated a little from the original code):

1testWidgets('Make sure the title is correct for the session', (tester) async {
2 await tester.runAsync(() async {
3 final container = await _pumpProviders(tester);
4 // Do some setup stuff elsewhere...
5
6 final titleLabel = await container.read(sessionTitleProvider.future);
7 expect(titleLabel, contains("#title"));
8 });
9});

The logic for the FutureProvider itself looks like this:

1final sessionTitleProvider = FutureProvider.autoDispose<String>((ref) async {
2 final repository = ref.read(timerEventRepositoryProvider);
3 final tag = await repository.getSessionTag();
4 return tag == "" ? "???" : "#$tag";
5});

In conclusion, when dealing with FutureProviders in Flutter unit tests, remember to access the future value and await it to ensure accurate testing of asynchronous operations within the provider.