[Part 5] Running the test fails with null safety enabled
flutternoob opened this issue · 1 comments
flutternoob commented
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)],
);
});
}
wxluoweihao commented
It seems to me that you specified the program may expect null reference object on type CounterCubit. Change "CounterCubit? counterCubit" to "late CounterCubit counterCubit", and replace any "counterCubit!" occurrences to "counterCubit" should work.
https://medium.com/flutterworld/flutter-null-safety-5d20012c2441
group('CounterCubit', () {
late CounterCubit counterCubit;
setUp((){
counterCubit = CounterCubit();
});
tearDown((){
counterCubit.close();
});
test('the initial state for the CounterCubit is CounterState(counterValue:0)', () {
expect(counterCubit.state, CounterState(counterValue: 0, wasIncremented: false));
});
blocTest('the cubit should emit a CounterState(counterValue: 1, wasIncremented:true) when cubit.increment() function is called',
build: () => counterCubit,
act: (cubit) => counterCubit.increment(),
expect: () => [CounterState(counterValue: 1, wasIncremented: true)],
);
blocTest('the cubit should emit a CounterState(counterValue: -1, wasIncremented:false) when cubit.decrement() function is called',
build: () => counterCubit,
act: (cubit) => counterCubit.decrement(),
expect: () => [CounterState(counterValue: -1, wasIncremented: false)],
);
});