How to Unit Test in Flutter Using GetX: Step-by-Step Guide

Bagus Kurnianto
6 min readMar 14, 2023

--

Photo by Joshua Lawrence on Unsplash

Unit testing is a critical aspect of any software development process. It helps developers catch bugs early, ensure code quality, and facilitate refactoring. Flutter is a popular framework for building cross-platform mobile applications, and it comes with robust tools for unit testing. In this article, we’ll explore how to write unit tests in Flutter using the GetX package.

What is Unit Testing?

Unit testing is a software testing technique in which individual units or components of a software application are tested in isolation. The goal of unit testing is to ensure that each unit of code is working as intended. It involves writing automated tests that check the behavior of the code under different conditions.

There are several benefits to unit testing, including:

  • Catching bugs early in the development process
  • Ensuring code quality
  • Facilitating refactoring
  • Reducing the time and cost of software development
  • Increasing confidence in the codebase

In Flutter, there are several types of unit tests, including integration tests, widget tests, and plain unit tests. In this article, we’ll focus on plain unit tests.

What is GetX?

GetX is a Flutter package that provides a simple and powerful state management solution for Flutter applications. It offers reactive programming, dependency injection, and other features that make it easier to develop robust and scalable Flutter applications. GetX is also an excellent package for unit testing in Flutter.

Some key features of GetX include:

  • Reactive programming
  • Dependency injection
  • Navigation management
  • Internationalization and localization support
  • Automated memory management

Why use GetX for unit testing? GetX provides several benefits for unit testing in Flutter:

  • It offers a simple and intuitive syntax for writing unit tests
  • It provides a powerful set of tools for simulating user actions and validating results
  • It facilitates easy integration with other testing frameworks, such as Mockito and TestWidgets

In the next section, we’ll get started with writing unit tests using GetX.

Getting Started with GetX Unit Testing

Before we start writing unit tests, we need to set up a new Flutter project and add the GetX package to it. If you already have a Flutter project set up, you can skip this step.

  1. Open Android Studio or Visual Studio Code and create a new Flutter project.
  2. Add the GetX package to your Flutter project by adding the following line to your pubspec.yaml file:
dependencies:
get: ^4.6.1
  1. Run flutter pub get to download and install the package.

Now that we have a new Flutter project set up with GetX installed, we can start writing unit tests.

Writing Unit Tests with GetX

To write unit tests using GetX, we’ll create a new test file and import the necessary GetX packages.

  1. Create a new test file in your Flutter project by right-clicking on the test directory and selecting "New Dart File".
  2. Name the new file my_widget_test.dart.
  3. Add the following import statements to the top of your test file:
import 'package:flutter_test/flutter_test.dart';
import 'package:get/get.dart';

Now that we have our test file set up, we can start writing test methods.

Creating Test Methods

In GetX, test methods are created using the testWidgets function from the Flutter test package. The testWidgets function takes a callback function that builds the widget tree for the test. We'll create a simple test method to demonstrate how to use testWidgets with GetX.


void main() {
testWidgets('MyWidget should display text', (WidgetTester tester) async {
await tester.pumpWidget(
GetMaterialApp(
home: MyWidget(),
),
);
expect(find.text('Hello, World!'), findsOneWidget);
});
}

In this example, we’re using the testWidgets function to create a new test method called MyWidget should display text. The callback function builds the widget tree for the test by creating a new GetMaterialApp with a MyWidget as its home screen. We then use the expect function to check that the widget tree contains a text widget with the text "Hello, World!".

Writing Assertions

In unit testing, assertions are used to check that the code under test is behaving as expected. In GetX, we can use the expect function to write assertions.

For example, let’s say we have a simple counter app that increments a counter when a button is pressed. We can write a unit test to check that the counter increments when the button is pressed using GetX:

testWidgets('Counter increments when button is pressed', (WidgetTester tester) async {
await tester.pumpWidget(
GetMaterialApp(
home: CounterPage(),
),
);
final counterText = find.byKey(Key('counterText'));
final incrementButton = find.byKey(Key('incrementButton'));
expect(counterText, findsOneWidget);
expect(incrementButton, findsOneWidget);
expect(tester.widget<Text>(counterText).data, '0');
await tester.tap(incrementButton);
await tester.pump();
expect(tester.widget<Text>(counterText).data, '1');
});

In this example, we’re using the expect function to check that the counter starts at 0, the counterText and incrementButton widgets are present, the counter increments when the button is pressed, and the counter text updates to reflect the new count.

Using GetX to Simulate User Actions and Validate Results

GetX provides a powerful set of tools for simulating user actions and validating results. For example, we can use the controller and GetBuilder classes to test state changes in our app.

Let’s say we have a simple login screen that validates user credentials and displays an error message if the credentials are incorrect. We can write a unit test to check that the error message is displayed when the user enters invalid credentials using GetX:

testWidgets('Login screen shows error message for invalid credentials', (WidgetTester tester) async {
final email = 'test@example.com';
final password = 'password';
final wrongPassword = 'wrongpassword';
final emailField = find.byKey(Key('emailField'));
final passwordField = find.byKey(Key('passwordField'));
final submitButton = find.byKey(Key('submitButton'));
await tester.pumpWidget(
GetMaterialApp(
home: GetBuilder<LoginController>(
init: LoginController(),
builder: (_) => Scaffold(
body: Column(
children: [
TextField(
key: Key('emailField'),
onChanged: (value) => _.onEmailChanged(value),
),
TextField(
key: Key('passwordField'),
onChanged: (value) => _.onPasswordChanged(value),
),
ElevatedButton(
key: Key('submitButton'),
onPressed: () => _.onSubmit(),
child: Text('Submit'),
),
_.errorMessage.isNotEmpty
? Text(
_.errorMessage,
key: Key('errorMessage'),
)
: Container(),
],

In this example, we’re using the GetBuilder widget to create a new instance of the LoginController class and pass it to the builder callback function. The init parameter is used to initialize the state of the controller.

We then create a Scaffold widget with a Column widget as its child. The Column contains two TextField widgets for the email and password fields, an ElevatedButton widget for the submit button, and a Text widget for displaying error messages.

When the user enters their credentials and presses the submit button, the onSubmit method of the LoginController class is called. This method validates the user's credentials and sets the errorMessage property of the controller if the credentials are invalid.

In our test, we’re using the tester.enterText function to simulate the user entering their email and password into the email and password fields. We then use the tester.tap function to simulate the user pressing the submit button.

Finally, we use the expect function to check that the error message is displayed when the user enters invalid credentials. We're using the controller property of the GetBuilder widget to access the state of the controller and check the errorMessage property.

Conclusion

In this article, we’ve discussed how to write unit tests in Flutter using GetX. We’ve covered how to set up a test environment, how to use the testWidgets function to create tests, how to write assertions using the expect function, and how to use GetX to simulate user actions and validate results.

By writing unit tests for your Flutter apps using GetX, you can ensure that your code is working as expected and catch errors before they make it to production. Unit testing also helps you build more robust and maintainable apps over time.

If you’re new to unit testing, we encourage you to experiment with writing your own tests and see how they can improve the quality of your code. With a little practice, you’ll be writing tests like a pro in no time!

--

--