2

this is the test code `

testWidgets('invalid input for testtwo', (WidgetTester tester) async {
    final test_two = find.byKey(ValueKey('test2'));
    final fill_mark = find.byKey(ValueKey('fillmark'));

    await tester.pumpWidget(PopUpMarklist(id: 'someid'));
    await tester.enterText(test_two, '12');
    await tester.tap(fill_mark);
    await tester.pump();
    expect(find.text('please put the extra marks in the other section'),
        findsOneWidget);
    expect(find.text('please fill the result if no result just put 0.0'),
        findsNothing);
  });`

and the bloc provider is in the main.dart as follows `

...
    MaterialApp(
            home: MultiBlocProvider(
          providers: [
            BlocProvider(
              create: (context) => Teacher_bloc(TeacherUserRepository(
                  teacherProvider: TeacherUserRemoteProvider()))
                ..add(LoadTeacher()),
            ),
            BlocProvider(
              create: (context) =>
                  MarklistBloc(MarklistRepository(MarklistRemoteProvider())),
            ),
            BlocProvider(create: (ctx) => AuthBloc(authRepository)),
            BlocProvider<ParAccBloc>(
              create: (context) =>
                  ParAccBloc(ParentRepository(parentProvider: ParentApiProvider()))
                    ..add(LoadParAccs()),
            ),
            BlocProvider(
              create: (context) => TeacherAccBloc(
                TeacherRepository(teacherProvider: TeacherApiProvider()),
              )..add(LoadTeacherAccs()),
            ),
            BlocProvider<AnnouncemntBloc>(
                create: (context) => AnnouncemntBloc(
                        announcemntRepository: AnnouncemntRepository(
                            dataProvider: AnnouncemntDataProvider(
                      httpClient: http.Client(),
                    )))
                      ..add(AnnouncemntLoad())),
          ],
          child: MaterialApp.router(
            theme: currTheme,
            routeInformationParser: _router.routeInformationParser,
            routerDelegate: _router.routerDelegate,
            title: "sms-demo",
          ),
        ))`

the provider is in the main.dart ,i thought this code(PopUpMarklist) which is in an other file , will be able to access it.

`

class PopUpMarklist extends StatefulWidget {
  String id;
  Marklist? marklist;
  PopUpMarklist({Key? key, required this.id, this.marklist}) : super(key: key);

  @override
  State<PopUpMarklist> createState() => PopUpMarklistState();
}

class PopUpMarklistState extends State<PopUpMarklist> {
  final formKey = GlobalKey<FormState>();
  final testOneController = TextEditingController();
  final testTwoController = TextEditingController();


  @override
  Widget build(BuildContext context) {

return BlocConsumer<MarklistBloc, MarklistState>(
      listener: (context, state) {
        if (state is StudentMarkReturned) {
          testOneController.text = state.studentMark.testOne.toString();
          testTwoController.text = state.studentMark.testTwo.toString();
          
        }
      },
      builder: (context, state) {
        return Form(
          key: formKey,
          child: Container(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                TextFormField(
                  key: Key('test1'),
                  controller: testOneController,
                  keyboardType: TextInputType.number,
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    color: Color.fromARGB(255, 84, 81, 71),
                  ),
                  decoration: const InputDecoration(
                    hintText: 'Test one (10%)',
                    focusColor: Color.fromARGB(255, 84, 81, 71),
                  ),
                  validator: (String? testOne) {
                    if (testOne == null || testOne.isEmpty) {
                      return 'please fill the result if no result just put 0.0';
                    }
                    var test10 = double.parse(testOne);
                    if (test10 > 10) {
                      return 'please put the extra marks in the other section';
                    }
                    return null;
                  },
                ),
                TextFormField(
                  key: Key('test2'),
                  keyboardType: TextInputType.number,
                  controller: testTwoController,
                  textAlign: TextAlign.center,
                  style: const TextStyle(
                    color: Color.fromARGB(255, 84, 81, 71),
                  ),
                  decoration: const InputDecoration(
                    hintText: 'Test two (10%)',
                    focusColor: Color.fromARGB(255, 84, 81, 71),
                  ),
                  validator: (String? testTwo) {
                    if (testTwo == null || testTwo.isEmpty) {
                      return 'please fill the result if no result just put 0.0';
                    }
                    var test10 = double.parse(testTwo);
                    if (test10 > 10) {
                      return 'please put the extra marks in the other section';
                    }
                    return null;
                  },
                ),
                
                
                ElevatedButton(
                  key: Key('fillmark'),
                  style: ButtonStyle(
                    backgroundColor: MaterialStateProperty.all<Color>(
                        const Color.fromARGB(255, 106, 104, 99)),
                  ),
                  onPressed: () {
                    final formValid = formKey.currentState!.validate();
                    if (!formValid) return;

                    final marklistBloc = BlocProvider.of<MarklistBloc>(context);
                    marklistBloc.add(Edit(
                        studentId: widget.id,
                       
                        testtwo: int.parse(testtwoController.text),
                        ;
                   
                    GoRouter.of(context).pushNamed("teacher homepage");
                  },
                  child: Text("submit"),
                )
              ],
            ),
          ),
        );
      },
    )}}

` and this is the error thrown in the debug console

`══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following ProviderNotFoundException was thrown building PopUpMarklist(state:
PopUpMarklistState#96199):
Error: Could not find the correct Provider<MarklistBloc> above this BlocConsumer<MarklistBloc,
MarklistState> Widget

This happens because you used a `BuildContext` that does not include the provider
of your choice. There are a few common scenarios:

- You added a new provider in your `main.dart` and performed a hot-reload.
  To fix, perform a hot-restart.

- The provider you are trying to read is in a different route.

  Providers are "scoped". So if you insert of provider inside a route, then
  other routes will not be able to access that provider.

- You used a `BuildContext` that is an ancestor of the provider you are trying to read.

  Make sure that BlocConsumer<MarklistBloc, MarklistState> is under your
MultiProvider/Provider<MarklistBloc>.
  This usually happens when you are creating a provider and trying to read it immediately.

  For example, instead of:

  ```
  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // Will throw a ProviderNotFoundError, because `context` is associated
      // to the widget that is the parent of `Provider<Example>`
      child: Text(context.watch<Example>().toString()),
    );
  }
  ```

  consider using `builder` like so:

  ```
  Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // we use `builder` to obtain a new `BuildContext` that has access to the provider
      builder: (context, child) {
        // No longer throws
        return Text(context.watch<Example>().toString());
      }
    );
  }
  ```

If none of these solutions work, consider asking for help on StackOverflow:
https://stackoverflow.com/questions/tagged/flutter

The relevant error-causing widget was:
  PopUpMarklist
  PopUpMarklist:file:///C:/Users/Yosep/OneDrive/Desktop/flutter%20project/sms_demo/test/fillMarklist_test.dart:26:29

When the exception was thrown, this was the stack:
#0      Provider._inheritedElementOf (package:provider/src/provider.dart:343:7)
#1      Provider.of (package:provider/src/provider.dart:293:30)
#2      ReadContext.read (package:provider/src/provider.dart:649:21)
#3      _BlocConsumerState.initState (package:flutter_bloc/src/bloc_consumer.dart:108:36)
#4      StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4893:57)
#5      ComponentElement.mount (package:flutter/src/widgets/framework.dart:4729:5)
...     Normal element mounting (9 frames)
#14     Element.inflateWidget (package:flutter/src/widgets/framework.dart:3790:14)
#15     Element.updateChild (package:flutter/src/widgets/framework.dart:3524:20)
#16     RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1198:16)
#17     RenderObjectToWidgetElement.update (package:flutter/src/widgets/binding.dart:1175:5)
#18     RenderObjectToWidgetElement.performRebuild (package:flutter/src/widgets/binding.dart:1189:7)
#19     Element.rebuild (package:flutter/src/widgets/framework.dart:4477:5)
#20     BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2659:19)
#21     AutomatedTestWidgetsFlutterBinding.drawFrame (package:flutter_test/src/binding.dart:1128:19)
#22     RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:363:5)
#23     SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1144:15)
#24     SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1081:9)
#25     AutomatedTestWidgetsFlutterBinding.pump.<anonymous closure> (package:flutter_test/src/binding.dart:995:9)
#28     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#29     AutomatedTestWidgetsFlutterBinding.pump (package:flutter_test/src/binding.dart:982:27)
#30     WidgetTester.pumpWidget.<anonymous closure> (package:flutter_test/src/widget_tester.dart:548:22)
#33     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#34     WidgetTester.pumpWidget (package:flutter_test/src/widget_tester.dart:545:27)
#35     main.<anonymous closure> (file:///C:/Users/Yosep/OneDrive/Desktop/flutter%20project/sms_demo/test/fillMarklist_test.dart:26:18)
#36     main.<anonymous closure> (file:///C:/Users/Yosep/OneDrive/Desktop/flutter%20project/sms_demo/test/fillMarklist_test.dart:22:44)
#37     testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:170:29)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following StateError was thrown running a test:
Bad state: No element

When the exception was thrown, this was the stack:
#0      Iterable.single (dart:core/iterable.dart:654:25)
#1      WidgetController.state (package:flutter_test/src/controller.dart:156:42)
#2      WidgetTester.showKeyboard.<anonymous closure> (package:flutter_test/src/widget_tester.dart:1042:42)
#3      WidgetTester.showKeyboard.<anonymous closure> (package:flutter_test/src/widget_tester.dart:1041:39)
#6      TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#7      WidgetTester.showKeyboard (package:flutter_test/src/widget_tester.dart:1041:27)
#8      WidgetTester.enterText.<anonymous closure> (package:flutter_test/src/widget_tester.dart:1077:13)
#9      WidgetTester.enterText.<anonymous closure> (package:flutter_test/src/widget_tester.dart:1076:39)
#12     TestAsyncUtils.guard (package:flutter_test/src/test_async_utils.dart:71:41)
#13     WidgetTester.enterText (package:flutter_test/src/widget_tester.dart:1076:27)
#14     main.<anonymous closure> (file:///C:/Users/Yosep/OneDrive/Desktop/flutter%20project/sms_demo/test/fillMarklist_test.dart:27:18)
<asynchronous suspension>
<asynchronous suspension>
(elided 5 frames from dart:async and package:stack_trace)

The test description was:
  invalid input for testtwo
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: invalid input for testtwo

✖ invalid input for testtwo
Exited (1)

`

i used Go router for routing so how do i get resolve this issue thanks in advance.

yoseph
  • 21
  • 3

1 Answers1

1

welcome to the community.

Widget testing is for testing individual widgets or pages in isolation from other components of the application. When testing a widget do not test bloc or domain layer or data layer(for that we have integration testing).

Hence you need to mock the bloc that are necessary for that page. You should see some examples for widget testing or simpler tests in bloc examples these are some good example repos see their widget tests.

You are missing mocking you will need mocktail and bloc_test. Read their documentation for better understanding on mocks.

testWidgets('invalid input for testtwo', (WidgetTester tester) async {
    // mocks
    whenList(bloc).thenAnswer((_) => Stream.fromIterable([]));
    when(() => bloc.state).thenAnswer((_) => const BlocState());
    .. other bloc mocks here.

    final test_two = find.byKey(ValueKey('test2'));
    final fill_mark = find.byKey(ValueKey('fillmark'));
    
    await tester.pumpWidget(
      MultiRepositoryProvider(
        providers: [
          RepositoryProvider<TeacherRepo>(
            create: (context) => MockTeacherRepo(),
          ),
          ... all other repos here
        ],
        child: MultiBlocProvider(
          providers: [
            BlocProvider.value(value: Teacher_bloc()),
            ... all other blocs here
          ],
          child: MaterialApp(
            child: PopUpMarklist(),
          ),
        ),
      ),
    );

    await tester.enterText(test_two, '12');
    await tester.tap(fill_mark);
    await tester.pump();
    expect(find.text('please put the extra marks in the other section'),
        findsOneWidget);
    expect(find.text('please fill the result if no result just put 0.0'),
        findsNothing);
});

I suggest you should look for articles tutorial before asking question as it can be a lot more informative and will help you to ask the right question. You can further read about widget testing here.

Ritesh Singh
  • 782
  • 9
  • 19