1

I'm trying to write a test for a row of buttons. The buttons should be enabled / disabled depending on a flag provided by a controller class.

class UserSettingsButtonRow extends ConsumerWidget {
  const UserSettingsButtonRow({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ref.watch(userSettingsControllerProvider);
    UserSettingsController controller =
        ref.read(userSettingsControllerProvider.notifier);

...

When I test this manually in the context of the whole program everything works fine. However I'd like to automate this test.

This is my test:

@GenerateNiceMocks([MockSpec<UserSettingsController>()])

void main() {
  testWidgets(
    'UserSettingsButtonRow - buttons enabled',
    (tester) async {
      // check if two buttons are enabled
      UserSettingsController settingsController = MockUserSettingsController();
      when(settingsController.hasValueChanged()).thenAnswer((_) => true);

      await tester.runAsync(
        () async {
          await tester.pumpWidget(
            ProviderScope(
              overrides: [
                userSettingsControllerProvider
                    .overrideWith((ref) => settingsController),
              ],
              child: const MaterialApp(
                home: Material(
                  child: UserSettingsButtonRow(),
                ),
              ),
            ),
          );
        },
      );

      await tester.pumpAndSettle();
      expect(find.byType(ElevatedButton), findsNWidgets(2));

      List<ElevatedButton> buttons = find
          .byType(ElevatedButton)
          .evaluate()
          .map((e) => e.widget as ElevatedButton)
          .toList();
      for (ElevatedButton button in buttons) {
        expect(button.enabled, isTrue);
      }
    },
  );

<.......>

My problem is that a assertion in the build() method of my widget is not fulfilled.

When the automated test comes to

ref.watch(userSettingsControllerProvider);

I get the following exception:

Exception has occurred.
_AssertionError ('package:riverpod/src/framework/element.dart': Failed assertion: line 439 pos 9: 'getState() != null': Bad state, the provider did not initialize. Did "create" forget to set the state?)

I can't find many examples on testing / mocking with StateNotifierProviders. Can somebody help me out and tell me what's wrong here?

Thanks for your help!

I tried the solution from what is the correct approach to test riverpod with mockito but the atttribute state is not supported any more.

Riverpod Testing: How to mock state with StateNotifierProvider? is not a solution either for me as I want to override the hasValueChanged() method from the Controller.

0 Answers0