Testing: Mock and Stubs
--
In your software engineering career, it is you will likely come across software testing. Software testing is basically making test cases before we go into the development (coding) process of the software. It acts as a code guardian for the code we make so that bugs don’t appear whenever you or other developers touch back or make integrations with the code you’ve made before. You can check more about testing in this article I made.
That’s enough about testing in general. Now, lets go more in depth. There are techniques used in testing. In this article, I will be covering the techniques of mocking and stubbing followed by some examples used in the project my team and I are developing.
Mocking
Mocking is creating a fake version of an internal or external service that helps test run faster and more reliably. Mocking is mostly used in unit tests where a unit that is being tested depend on other units or services. It helps isolate the behaviors of the tested unit by replacing the other unit’s behaviors by creating the fake version of it that simulates the behavior as if it is the real unit. In short, mocking is creating a fake version of a unit to simulate the real behavior of it.
Stubbing
Stubbing is almost similar to mocking. The difference is that stubbing only mocks a certain behavior rather than mocking the entire object. Stubbing is great when the tested unit relies on a certain behavior of another service. Stubbing is also great when other units are also not developed and you want to have a temporary replacement that give the same output as that of the actual unit.
When to use mocking and stubbing?
I’ve explained a bit when to use mocking and stubbing above. But, the main reason to use mocking and stubbing is when you have system calls or external calls to other services, for example accessing a database. When testing, it is not efficient when we do a create
or delete
call since the data created or deleted will not be used therefore useless. Additionally, it takes more steps to clean up since we’d have to delete the created data manually. Mocking and stubbing helps this problem.
Using mocks and stubs help isolate the unit being tested. For example, you’d like to send a get request to fetch a list of details of the user to the API that connects to the database. The problem is that to send a request and receive back a response takes time. We’d want to avoid that by creating a stub for the API call which will take less time since it immediately returns the list of details of the user.
Mock and Stub Testing Example
So below is one of the tests I made for a project my team and I are currently developing. It is in dart, but should be easy to understand even if you haven’t learnt or used it before. Also, it might not be the best practice, but the point of it is to show how to do mocking and stubbing.
Dart tests don’t support http
calls out, so what we do is create a mock instance of the APIProvider
object and then stub the Client
of the APIProvider
by specifying on what the client will respond if a HTTP call is run. In this case, the data doesn’t matter since we only want to check if the client does return a response the same as to what it will return when the login
method will be created.
Below is also another example of one of my tests for a login widget.
In the example above, we tell dart to generate a mock file of the APIProvider
(We can generate the file by using the flutter pub run build_runner build
, make sure to have build_runners
in your pubspec.yaml
) and initializing at the start of the test. We then use the when
function from the mockito
package to specify that if the login
function of the APIProvider gets called, then return the response we expect as if it was the real instance.
Last Thoughts
All in all, mocking and stubbing helps us isolate the unit being tested from the dependencies it has. We do not have to worry about the behavior of the dependencies (for example, the response of an API call as shown in the example above) and also is time efficient since mocking and stubbing immediately returns what we have already specified before.