Skip to content

[Part 5] Running the test fails with null safety enabled #5

@flutternoob

Description

@flutternoob

I am trying to run the code with null safety enabled in the project. I keep getting the following error when I run the test on counter_cubit_test.dart:

Null check operator used on a null value

This is the code in the counter_cubit.dart file:

import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';

part 'counter_state.dart';

class CounterCubit extends Cubit<CounterState> {
  CounterCubit() : super(CounterState(counterValue: 0));

  void increment() => emit(
      CounterState(counterValue: state.counterValue! + 1, wasIncremented: true));

  void decrement() => emit(CounterState(
      counterValue: state.counterValue! - 1, wasIncremented: false));
}

This is the code in the counter_state.dart file:

part of 'counter_cubit.dart';

class CounterState extends Equatable {
  final int? counterValue;
  final bool? wasIncremented;

  CounterState({required this.counterValue, this.wasIncremented});

  @override
  List<Object> get props => [this.counterValue!, this.wasIncremented!];
}

This is the code in the main.dart file:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_counter_bloc/cubits/counter_cubit.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(
        primaryColor: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: BlocProvider<CounterCubit>(
        create: (context) => CounterCubit(),
        child: MyHomePage(title: "Flutter Demo Home Page"),
      ),
    );
  }
}

///Used a stateless widget since state is handled by the Bloc library in this case. I referred the
///following link: https://stackoverflow.com/questions/58864869/flutter-state-management-bloc-stateless-vs-stateful-widget
class MyHomePage extends StatelessWidget {
  final String? title;

  const MyHomePage({Key? key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(title!),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("You have pushed this button this many times:"),
            BlocConsumer<CounterCubit, CounterState>(
              ///Refactored the if...else block into a function to show the SnackBar Widget
                listener: (context, state) => snackBarFunction(state.wasIncremented!, context),
                ///Refactored the if...else block into a function that returns a Text widget
                builder: (context, state) => counterText(state.counterValue!, context)),
            SizedBox(height: 24),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                FloatingActionButton(
                  onPressed: () => BlocProvider.of<CounterCubit>(context).decrement(),
                  heroTag: Text("$title"),
                  tooltip: "Decrement",
                  child: Icon(Icons.remove),
                ),
                FloatingActionButton(
                  onPressed: () => BlocProvider.of<CounterCubit>(context).increment(),
                  heroTag: Text("$title #2"),
                  tooltip: "Increment",
                  child: Icon(Icons.add),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

///This function is used to show the snack bar widget depending on whether the counter was incremented
///or decremented
void snackBarFunction(bool counterState, context) {
  if (counterState == true) {
    ///Scaffold.of(context).showSnackBar(snackBar) is deprecated
    ///Using ScaffoldMessenger.of(context).showSnackBar(snackBar) instead
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text("Incremented!"),
      duration: Duration(milliseconds: 300),
    ));
  } else {
    ScaffoldMessenger.of(context).showSnackBar(SnackBar(
      content: Text("Decremented!"),
      duration: Duration(milliseconds: 300),
    ));
  }
}

///This function is used to change the returned Text widget in accordance with the value of the counter
Text counterText(int counterValue, context) {
  if (counterValue < 0) {
    return Text("BRR, Negative $counterValue",
        style: Theme.of(context).textTheme.headline4);
  } else if (counterValue % 2 == 0) {
    return Text("YAAAY $counterValue",
        style: Theme.of(context).textTheme.headline4);
  } else if (counterValue == 5) {
    return Text("HMM, NUMBER 5", style: Theme.of(context).textTheme.headline4);
  } else {
    return Text("$counterValue",
        style: Theme.of(context).textTheme.headline4);
  }
}

This is the code in the counter_cubit_test.dart file:

import 'package:flutter_counter_bloc/cubits/counter_cubit.dart';
import 'package:test/test.dart';
import 'package:bloc_test/bloc_test.dart';

void main() {
  group("CounterCubit", (){

    CounterCubit? counterCubit;

    setUp((){
      counterCubit = CounterCubit();
    });
    tearDown((){
      counterCubit!.close();
    });

    test("Initial state of CounterCubit is CounterState(counterValue: 0)", () {
      expect(counterCubit!.state, CounterState(counterValue: 0));
    });

    blocTest<CounterCubit, CounterState>(
      'the CounterCubit should emit a CounterState(counterValue:1, wasIncremented:true) when the increment function is called',
      build: () => counterCubit!,
      act: (cubit) => cubit.increment(),
      expect: () => <CounterState>[CounterState(counterValue: 1, wasIncremented: true)],
    );

    blocTest<CounterCubit, CounterState>(
      'the CounterCubit should emit a CounterState(counterValue:-1, wasIncremented:false) when the decrement function is called',
      build: () => counterCubit!,
      act: (cubit) => cubit.decrement(),
      expect: () => <CounterState>[CounterState(counterValue: -1, wasIncremented: false)],
    );
  });
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions