Unit test express controller
How to test Express controller functions using unit testing principles
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
This lesson preview is part of the Pain Free Mocking with Jest course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Pain Free Mocking with Jest, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
[00:00 - 00:18] In this example, we'll explore how to write effective unit tests for an express controller function. By testing our controller function, we can ensure that our API endpoints behave as expected and undo requests correctly. Now remember the magic of automated tests, which is instant feedback.
[00:19 - 04:10] This means we can say goodbye to tedious set of procedures like installing express, defining routes and then implementing our controller functions just to see if our check password function works or not. With the power of unit testing, we can isolate our function and test it directly, eliminating unnecessary dependencies and getting immediate feedback on its functionality. This speeds up our development process and makes it more predictable and efficient. So instead of wasting time setting up the entire express framework, we can simply focus on writing our functions and testing its behavior in isolation. This allows us to identify and fix any issues quickly and easily before they have a chance to snowball into bigger problems it's around. In this example, we'll create the sign up function in the author.js file inside the controllers directory in the source folder. This function will handle the sign up logic of our application. Our sign up function accepts a user object in the request body and depends on the hash password and creates user functions. The sign up function will perform the necessary operations to create a new user in our system. To write unit tests for the sign up function, we need to consider the entry and exit point of the application. The entry point consists of the request and response parameters, while the exit point includes the return value in the response object and any state mutations that may occur. In this example, we 'll be using unit testing principles to mock the collaborators of our sign up function. By mocking the collaborators, we can ensure that our unit tests focus solely on the behavior of the sign up function. In this example, we're using mocking goods to mock the behavior of our database. This means that when our sign up function interacts with the database, it will be interacting with the mocked version provided by mocking goods. We'll also implement another test case where we don 't use mocking goods rather we'll use just the mock function. In this example, we have created test cases for our HTTP sign up endpoints controller. The first test is for the happy path, which is given valid data, our system on that unit should return the appropriate response, while the second test is for the sad path, which is given invalid or erroneous data, our system on that unit should handle any errors thrown, and return an appropriate error response. You want to follow similar approach to further improve the robustness of your system unit. In the first test, in our orange step, we created the user object and DB user, which mimics how the user object will be stored in the database. We also used mocking goods to mock the find one method of Mongoose, and we instructed to return undefined. We also mocked the save method to return DB user. We then created our mock response and mock request objects. The mock response is an object that contains status, which is a stop using just dot FM function. And we use mock return value to determine what status should return whenever it is executed. Yeah, it will return an object that contains JSON, which is a stop. We then go ahead to execute our sign up controller. And we assess that mock response, the status must have been called, and that it was called with 201. I had to run this test and it should run successfully.
[04:11 - 04:54] In the second test, which is for our side path, we created our user object and DB user, similar to what we did in the first test. But what is different here is in the mock response, which is an object. It contains status. status is also a stop using just dot FM function. But here we're using mock implementation, unlike what we did in the first test, where we used mock return value. mock implementation takes in a function. And we just want to return another object, which contains JSON, which is also a stop with defined the mock this one here. And over here, we've used mocking goes to mock mongus find run method to return DB user.
[04:55 - 06:28] This is important because we want to test this scenario where user already exists with this email . In our signup endpoint controller, we check if the user already exists in the database by calling user with email exist. And if this returns true, we'll return a status with 400. The user with email exist function simply queries the database by calling the find run method and returns true if the user exists or returns false if the user does not exist. Hence, the reason why we had to mock the user find one method to return DB user. So we are left to test scenario where the user already exists in the database. And we go ahead to execute our signup controller function. And I said that the mock response does status was called and it was called with 400. And we also check the mock JSON that it was called and that it was called with this object status field message email taking. I go ahead and run this test and it should run successfully. The other implementation of our test case is this in here, we are not using mocking goes, but rather, we are mocking one of the collaborators of the signup controller function, which is this function user with email exist. And here, we're not using spies or stops rather we're using m ocks. The first thing is we import the function and then we create a mock of the entire module that we imported here.
[06:29 - 07:25] The interesting bit goes into the body of the callback function. The first thing we want to do is create an actual copy of the entire module using just the require actual. And we stored that in original user service. We then created this variable partially mock user service. And we want to mock this user with email exist and replace it with a stop that always returns true. Finally, we want to return this object made up of the original user service and we're using the spread operator here, meaning it will return everything in the module. And we also use the spread operator to return the partially mock user service, which returns user with email exist. And this will replace user with email exist function. I haven't done this. We're going to the body of our test case.
[07:26 - 08:52] We created our user object, we goes into the mock request, and we then created the mock response using a stop here that returns an object that contains JSON, which is also a stop. In the next step, we executed our signup controller function. And then we made our sessions using the expect function, which I give the status mock was called. And if the status mock had been called with 400, one of the new constructs here is just the clay marks. Previously in our just.config.js file, we use the clay marks and the other value here, which is restore marks to make just automatically reset or clear marks. What's in here, we are using the just or clear marks. It 's basically doing the same thing, but just is taking over the responsibility for us. If we have like two or three marks, just will automatically clear all of those marks. In summary, writing unit tests for express controllers is crucial for ensuring the correctness of our API points. By following unit testing principles, mocking collaborators are using tools like tests dot mock or mocking goose, we can write effective tests that verify the behavior of our controller functions.