In my last post I created the Providers and Bloc for our messaging app’s registration page. Today we’ll be writing tests for the Providers . Testing is a critical aspect of making sure applications continue to work as they are changed, and ensures that the quality of the software can be maintained and accidental modifications can be avoided. While one can develop a app without writing tests but in the long run and maintenance of the app, it is as necessary as writing the app itself.

What is Unit Testing?

Quoting from flutter docs,

A unit test tests a single function, method, or class. The goal of a unit test is to verify the correctness of a unit of logic under a variety of conditions. External dependencies of the unit under test are generally mocked out. Unit tests generally don’t read from or write to disk, render to screen, or receive user actions from outside the process running the test.

Setup

Testing classes which depend on external dependencies like Firebase can be a tough task, since ideally we would not want to call external dependencies in our tests. Instead what we do is create mock implementations of all the necessary classes. The key point here is,

We need not test the external dependencies (Firebase in this case), but rather test the code/logic of how the providers interact with them.

Which means that how Firebase processes the data does not matter to us. We care to test only the code which formulates the Provider’s logic. Let’s start by adding all the required dependencies first. Add mockito to your dev_dependencies in your pubspec.yaml.

mockito: ^4.1.0

Mockito is a powerful testing library using which we can mock classes and methods. I’ll explain more about its usage as we go along.

Testing Firebase Authentication

All the authentication related methods are part of the AuthenticationProvider . It has two external dependencies, FirebaseAuth and GoogleSignIn . We have created a constructor with optional parameters so that we can inject the mocked objects while testing.

Let’s mock them first. Create a file test/mock/FirebaseMock.dart . We’ll put all our Firebase related mocks here. Creating a mock is as easy as extending Mock class from Mockito package and implementing from the class we want to mock.

Create test/providers/AuthenticationProvider_test.dart . Let’s start by testing the signInWithGoogle method.

First we have created Mock objects from FirebaseAuthMock and GoogleSignInMock . Next we’re instantiating AuthenticationProvider and passing over these dependencies to it. Then we’re creating a FirebaseUser Mock. It has default hardcoded values and looks something like this,

Now let’s mock the signInWithGoogle method line by line.

is mocked as

And

is mocked as

And then we use expect and verify to check the output of the method.

when, is used to mock method calls. We can define what we want the methods to return and it’ll override the default behavior of the method with the one we define.

is used to mock method calls. We can define what we want the methods to return and it’ll override the default behavior of the method with the one we define. expect , takes in two parameters, in first one we call the signInWithGoogle method. In second we pass what we expect the output to be.

, takes in two parameters, in first one we call the method. In second we pass what we expect the output to be. verify, in this case is used to verify how many times a method is called during the test.

Similarly we write tests for the other methods as well.

Testing StorageProvider

The StorageProvider has just a one method which takes a file, uploads it to a path in FirebaseStorage and returns the download URL.

We start by creating a FirebaseStorage mock. This Provider will be trying to upload the file at root/path/our_new_file . Because of this we need to create StorageReference mock for all the three destinations. Let’s look at the uploadImage method before we start.

It is pretty simple with just 4 lines of code. Let’s mock it.

We first mock the ref() method to return rootReference . Then we say that everytime the putFile() method is called with any parameters, return the mocked storageUploadTask .

Then, everytime storageUploadTask.complete is called, return a Future of storageTaskSnapshot . This is supposed to be the snapshot to the file after it uploads, since no actual upload is happening here so we’ll have to mock a file reference here. We now say that everytime storageTaskSnapshot.ref() is called, return the fileReference object.

We then mock the download URL as Future on the fileReference object. and end it by expect-ing the URL we used while mocking as result.

Testing UserDataProvider

The last provider in the list is UserDataProvider . This has a number of methods and explaining them all here would not make sense. The method of testing is similar to what we did earlier. I have added comments to the code after every step for better understanding. Take a look.

So we’re done with writing the test. Let’s run them now.

flutter test — no-pub test/

And all the tests pass ! Nothing more joyous than the sight of all your tests passing.

Hit me up in the comments below or Twitter or Linkedin or Instagram if you have any queries or suggestions. See you guys in the next one!

Code Changes

#14 Registration Tests

How Can You Contribute?

Open issues with suggestion of better approaches or ideas for the app.

Connect with me on Twitter or Linkedin or Instagram.

Star the Github repository.

Share the series on Twitter.

Follow me on Github.

Posts In This Series

Show Your Support

Press the clap button below if you liked reading this post. The more you clap the more it motivates me to write better!