Unit Testing for Providers in Flutter

5,730

Solution 1

You need to wrap the widget you want to test in the providers used by that widget.

As such, you may want to write:

await tester.pumpWidget(
  Provider<TokenProvider>(
    child: SplashScreen(),
  ),
);

Solution 2

If you have repeated tests with such code, you can utilize extension

import 'package:provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:mockito/mockito.dart';

  Widget wrapWithMaterial() => MaterialApp(
    home: Provider<TokenProvider>(
      create: (_) => MockTokenProvider(),
      child: Scaffold(
        body: this,
      ),
    ),
  );

 class MockTokenProvider extends Mock implements TokenProvider {}

And now inside your test you could do

await tester.pumpWidget(
  SplashScreen().wrapWithMaterial()
);
Share:
5,730
Prudhvi Kumar Patthipati
Author by

Prudhvi Kumar Patthipati

Updated on December 17, 2022

Comments

  • Prudhvi Kumar Patthipati
    Prudhvi Kumar Patthipati over 1 year

    We have started a new project on Flutter in the TDD approach. I am using providers for State Management. While trying to write the Widget Testing we are facing the issue to test the providers. Can you please suggest with an example to write the unit testing for providers and widget injects the provider.

    I'm getting the following issue

    ══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════
    The following ProviderNotFoundException was thrown running a test:
    Error: Could not find the correct Provider above this SplashScreen Widget
    
    To fix, please:
    
    Ensure the Provider is an ancestor to this SplashScreen Widget
    Provide types to Provider
    Provide types to Consumer
    Provide types to Provider.of()
    Always use package imports. Ex: `import 'package:my_app/my_code.dart';
    Ensure the correct context is being used.
    

    ══╡ Splash Screen Code╞════════════════════════════════════

    import 'dart:async';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import '../../../routes.dart';
    import '../../constants/constants.dart';
    import '../../providers/provider.dart';
    import '../../services/navigation_service.dart';
    import '../../utils/utlis.dart';
    
    class SplashScreen extends StatefulWidget {
      @override
      SplashScreenState createState() => SplashScreenState();
    }
    
    class SplashScreenState extends State {
      void startTime() {
        const _duration = Duration(seconds: Preferences.splashScreenTime);
        Timer(_duration, _getInitialData);
        _getInitialData();
      }
    
      dynamic _getInitialData() async {
        final TokenProvider tokenProvider =
        Provider.of(context, listen: false);
    
        await tokenProvider.setAccessToken();
    
        navigationPage();
      }
    
      void navigationPage() {
        NavigationService.pushReplacementNamedTo(Routes.home_screen);
      }
    
      @override
      void initState() {
        super.initState();
        startTime();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.white,
          body: Stack(
            key: const Key('splashScreen_body'),
            fit: StackFit.expand,
            children: [
              Image.asset(
                'assets/images/flutter.png',
                key: const Key('splashScreen_image'),
              )
            ],
          ),
        );
      }
    }
    

    thank in advance