How to initalize a diffrent class and access its data while widget testing in flutter?

Issue

So I’m developing a flutter app and I’m using the height and width of the mobile to decide the padding.

I’m storing all the size configurations in size_config.dart

import 'package:flutter/material.dart';

class SizeConfig {
  static MediaQueryData _mediaQueryData;
  static double screenWidth;
  static double screenHeight;
  static double defaultSize;
  static Orientation orientation;

  void init(BuildContext context) {
    _mediaQueryData = MediaQuery.of(context);
    screenWidth = _mediaQueryData.size.width;
    screenHeight = _mediaQueryData.size.height;
    orientation = _mediaQueryData.orientation;
  }
}

I’m initializing the SizeConfig class in my splash_screen.dart

import 'package:flutter/material.dart';
import 'size_config.dart';
class SplashScreen extends StatefulWidget {
  const SplashScreen({ Key? key }) : super(key: key);

  @override
  _SplashScreenState createState() => _SplashScreenState();
}

class _SplashScreenState extends State<SplashScreen> {
  @override
  Widget build(BuildContext context) {
    SizeConfig().init(context);
    return MaterialApp(
      ...
    );
  }
}

And I’m using the width in signup_screen.dart like so

import 'package:flutter/material.dart';
import 'size_config.dart';

class SignUpScreen extends StatefulWidget {
  const SignUpScreen({Key? key}) : super(key: key);

  @override
  _SignUpScreenState createState() => _SignUpScreenState();
}

class _SignUpScreenState extends State<SignUpScreen> {
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(
        horizontal: SizeConfig.screenWidth * 0.08,
      ),
      child: ...
    );
  }
}

Everything is working fine but the problem starts when I’m testing the widgets. How I’m I supposed to call the init method and make sure that the value of SizeConfig.screenWidth is not null.
Here is my signup_screen_widget_test.dart

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets('SignUpScreen rendering test', (WidgetTester tester) async {
    await tester.pumpWidget(
      MaterialApp(
        home: SignUpScreen(),
      )
    );
    expect(find.text('Sign Up'), findsOneWidget);
  });
}

I tried looking up MockBuildContext but as far as I know that is only used to pass while testing methods that have BuilContext as a parameter.

This is the error I’m getting which is saying that SizeConfig.screenWidth is null

Output for SignupScreen rendering test
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building SignUpScreen(dirty, state:
_SignUpScreenState#de317):
The method '*' was called on null.
Receiver: null
Tried calling: *(0.08)

The relevant error-causing widget was:
  SignUpScreen

Thanks in Advance!

Solution

As width and height is static in SizeConfig class, which can set directly for the test for example

void main() {
  testWidgets('SignUpScreen rendering test', (WidgetTester tester) async {
    SizeConfig.width = 400
    SizeConfig.height = 760
    await tester.pumpWidget(
      MaterialApp(
        home: SignUpScreen(),
      )
    );
    expect(find.text('Sign Up'), findsOneWidget);
  });
}

or you can create a helper class for the tests which sets the SizeConfig height and width and use this helper function for creating test widgets

class HelperFunctions {
  static Widget createWidgetForTesting({Widget child}) {
    SizeConfig.screenHeight = 400;
    SizeConfig.screenWidth = 760;
    SizeConfig.orientation = Orientation.portrait;

    return MaterialApp(
      home: child,
      onGenerateRoute: router.generateRoute,
    );
  }
}

Answered By – Fahad Ali shaikh

Answer Checked By – David Marino (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *