60 Days of Flutter :Building a Messenger : Day 51–54 : Unit Testing Firebase Providers with Mockito
So I’ve been doing Unit Testing for the last one week and here’s what I think.
It’s more important than most people think it is. It is one of the earliest testing efforts performed on the code and the earlier defects are detected, the easier they are to fix.
It’s often the most avoided part of the entire SDLC, especially for small scale applications. Which is fine sometimes when the application is really small and is just a prototype but in other cases one should try to write as much tests as possible. This is how lot of developers react when they’re asked about tests.
This does not necessarily mean that you have to aim for 100% code coverage because let’s be real, that’s hard to achieve and might not be necessary in most cases. So try to test every part of the code which you feel that isn’t very basic or might break someday.
But How Do I Approach Testing?
For many beginners the biggest question is that how do I start writing tests? what exactly do they do? So in the most basic words,
A Unit Test is meant to check the behavior of the particular class/function by providing it a set of inputs and confirming that
- the execution flow is what we expected it to be.
- and the result is what we expect it to be.
Unit Testing the Providers
We’re using Firebase and I/O related stuff in all of our providers and so we need a way to mock them in our test environment. It’s a simple exercise and the easiest way to do it is,
- look at the function you’re testing, line by line,
- mock everything which needs to be mocked.
- connect the dots (link the behaviors of mock objects).
Let me show you how with a quick example.
We have a method in our ChatProvider
called getAttachments
. This method returns all the attachments of a particular type (1:Image, 2: Video, 3: File) for a particular Chat.
Let’s write the test for it.
- First call is to
FireStore
that means we need to create a mockFireStore
instance (FirestoreMock
is created using mockito. Check this post to see how).
fireStore.collection(Paths.chatsPath)
should return a collection.
- A
document(chatId)
call on this collection should give us theDocumentReference
.
chatDocRef.collection(Paths.messagesPath)
will return a CollectionReference.
- Whenever we call any query on this
messagesCollection
it will return us with aQuery
object. We have three queries in our query chain and we mock them like this:
Now you might be wondering why I’m returning the same object again and again? It’s because of one simple principle:
Always test your business logic (code) and not the functionality of the framework.
In this case the query functions are part of the Firebase Package and we can depend on them(the framework) to work properly. What we do need to make sure that the where
and the orderBy
queries are always part of the function call. So that the end result isn’t faulty. So we just simply create a mock query object and pass it till the end of the chain.
Lets remove
when(query.orderBy('timeStamp', descending: true)).thenReturn(query);
and this is what happens:
The chain is broken and so the tests fails. Pretty handy in case someone accidentally modify/delete the line!
- Next we mock the final message documents. (
messageDataMock
is part ofDataMock.dart
. Check Code Changes section to see it).
- And in the final step we call the
getAttachments
method for thechatId
and thefileType
we mocked above, and then verify that all the mocked results are of typeImageMessage
.
Run the tests and I bet seeing this message will make you feel like writing more and more tests.
This is just one test. I’ve written tests for all the Providers. Check out the code in their respective gists:
And this will be it for the day. Do check the code changes section for the data objects I’ve created for mocking. In the next post we’ll touch upon Firebase Database rules.
Code Changes
#40 Added tests for all the providers
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
- 60 Days Of Flutter : Building a Messenger from Scratch
- 60 Days of Flutter : Day 1 : Creating the App
- 60 Days of Flutter : Day 2 : Setting Up A CI With Flutter
- 60 Days of Flutter : Day 3–4 : Building a Chat Screen in Flutter
- 60 Days of Flutter : Day 4–5 : Widget Testing With Flutter
- 60 Days of Flutter : Day 6–7 : Implementing a Slideable Widget Using Bottomsheet in Flutter
- 60 Days of Flutter : Day 8 : Changing The Launcher Icon and Implementing GestureDetector
- 60 Days of Flutter : Day 9–10–11 : Creating Awesome Register Screen in Flutter
- 60 Days of Flutter : Day 12–14 : Understanding BLoC Pattern in Flutter
- 60 Days of Flutter : Day 15–17 : Implementing Registration Screen using ‘flutter_bloc’
- 60 Days of Flutter : Day 18–19 : Unit Testing in Flutter using ‘ mockito’
- 60 Days of Flutter : Day 20–21 : Unit Testing a Bloc in Flutter
- 60 Days of Flutter : Day 22–23 : Building a Modern Contacts Page in Flutter
- 60 Days of Flutter : Day 24–26 : Building a Animated Progress Fab and the Contacts Bloc in Flutter
- 60 Days of Flutter : Day 27–29 : Sending and Retrieving Messages from Firebase using BLOC
- 60 Days of Flutter : Day 30–32 : Firebase Chat UI using Stream and Bloc
- 60 Days of Flutter : Day 33–35 : Paginating data from Firestore using Firebase Queries
- 60 Days of Flutter : Day 36–38 : Seamlessly Upload Files to Firebase Storage
- 60 Days of Flutter : Day 39–41 : One UI Inspired Attachments Showcase Page
- 60 Days of Flutter : Day 42–45 : Creating the Home Page & Quick Peek BottomSheet for Messages
- 60 Days of Flutter : Day 45–47 : Adding Dark Mode to a Flutter App
- 60 Days of Flutter : Day 48–50 : Creating the Settings Page using Bloc
- 60 Days of Flutter : Day 51–54 : Unit Testing Firebase Providers with Mockito
- 60 Days of Flutter : Day 55–56 : Deploying Firestore Security Rules using Firebase CLI
- 60 Days of Flutter : Day 60 : Wrapping It Up
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!