Unit Testing with Jest (Mocking with Sequelize)
I believe hope you all got a chance to go through the article Unit Testing with Jest which explains what, why, and how we can write unit tests using the Jest framework.
Now let's move on to another level and see how we can test code that uses third-party libraries or extensions or services which are in use in our code but can’t be unit tested.
Some of the use cases are where we use jest mocking to unit test our logic.
- In the case of API logic and when unit testing, we shouldn’t insert data into the database to test the whole controller logic, which isn’t a good idea, and mocking comes in handy here.
- When consuming an API in the front end we can mock the service call to test our logic to handle Success/Failed responses.
- Using an AWS-SDK package and consume its services, but when unit testing that piece of code, we can’t use the real AWS keys and the real services, so we need to mock any such services which we inject into our methods.
These are some day-to-day areas where mocking comes into the picture for unit testing a piece of software.
Prerequisites
- Node Express project
- Integrate Sequelize ORM with Postgres Database (To give you an overview about Sequelize assume that it is the same as MongoDB but for a relational Database, without raw queries)
- Jest framework installed
let's begin with the first example. Create a simple node server that has a single API that returns a couple of users with some dummy data from the Postgres Database.
Once you have written an API to get users to list, the code looks something similar to the below screenshot (route and the controller). So basically we have a single route /users
which will fetch a list of users inside the database.
Now let's say we want to unit test the controller method getUsers
how do we do that without hitting the Database as it involves real user data which we shouldn't access? this is where we can use Jest Mocks.
According to Jest documentation here is what mock is defined
Mock functions allow you to test the links between code by erasing the actual implementation of a function, capturing calls to the function (and the parameters passed in those calls), capturing instances of constructor functions when instantiated with
new
, and allowing test-time configuration of return values
In simpler terms, it will override the real identity of a piece of software and return data that looks like the original code is returning (similar to shadowing a piece of code).
So keeping this in mind we can now mock that database call and return our data and also we can break the code so as to catch the error in the catch block.
Case 1: Mock database call and return users
In the test file, I have used a mock response for the data query to return instead of making a real query execution. If you observe we have defined our mock response using jest.SpyOn we mocked our data access layer method db.users.findAll which will return the mocked response.
To sum up we can mock any API call, SDK integrations, packages, etc in your unit testing with mock responses to test your application logic for varied cases could be positive or negative tests.
NOTE:
Of course, we can perform unit testing without mocking the data access layer but instead, we have to create a test environment with a test database and test data. It could be other services as well like AWS, Zoom SDK, etc. We can have our own test environments created and provide the respective keys and secret IDs so that we don’t need to mock the respective logic in our application code.