What I have learned writing Mock Unit Tests

Chris Harwell
5 min readFeb 22, 2021

--

Thumbnail Image

This past week I have had the opportunity to brush up on my testing skills. I started out the week excitedly thinking,
“Finally, a project that I will be able to write tests for!”. That excitement slowly came to a halt. Here’s why:

The app I’m working on has a ton of conditional rendering. Depending on the users role they will see something either
slightly different or completely different from a user with a different role. This means, when testing the endpoints I had a problem.

I had authorization middleware, I thought initially I could just do what the endpoints do and provide credentials and “mock” the login manually.

Authorization Middleware

But, I found out that wasn’t going to work. After doing a ton of googling and
reading 5–6 articles, I asked a colleague for some help. I found out that the articles I read where correct and that to mock the middleware all i had to do was use a test that looks something like this:

jest.mock(“/path/to/middleware.js”, () => {
jest.fn((req, res, next) => next());
});

My first thoughts where something like “This makes no sense”, or “I don’t understand how this mocks the behavior of
the middleware”. I soon realized that it didn’t make sense to me because I thought we where mocking the middleware’s
behavior, as far as I’m aware all that next() does is call the next middleware. In all honesty, it still doesn’t make sense to me, but I’ve kinda just accepted that it works.

After review though, I’m pretty sure all the code does is skip over the middleware, so in a way it bypasses the middleware but I’m not exactly sure.

Next I ran into another problem, if all of the endpoints return certain data based on a users role, how do I assign a role? Furthermore, how do i mock the data in the database without effecting the actual database or using more
resources to create a database specifically for tests? The solution i found was using a library called Faker.js. I then created a generator function that generates random data for the tests.

Now that i had the database mocked, and the middleware mocked it was off to the races to write tests for the endpoints. You may be asking at this point
“Why didn’t you follow best practices and write unit tests as you where building out endpoints?”, and the answer to that is simple the client specifically asked that we finish MVP within a certain time frame and write unit tests, polish features, and fix bugs after MVP was complete.

After spending roughly 6 hours with 2 other developers trying to figure out why our tests weren’t working when the auth middleware was added to the endpoints in our Node/Express API i decided that we should work on the frontend tests since they should be more straightforward and easy to complete. I concluded that if we get integration tests as well as at least 80% test coverage on the frontend and good documentation on the backend we should be good to go.

I ran the problem by our team lead and he said he wanted that specific endpoint tested if possible. Upon doing research on unit tests to refresh my memory on the topic, i realized that 90% test coverage of every
component within the React app wasn’t feasible in 2 weeks given my lack of experience writing unit tests. I made the decision to focus on the React side of testing for the time being. As it turns out my decision was a good one, we immediately made progress and had 2 passing tests withing 20 minutes. We decided that since our code wasn’t very “testable” for unit tests we could do alot of the testing for stateful stuff with integration tests using Cypress.

During this project i have re-learned how to write unit tests in jest as well as write integration tests in Cypress. As with every project, finding the balance between clean code and finishing MVP by the deadline has been a
challenge. Every project is different, this client happened to give us a deadline and asked if we could do it within that time. We all discussed it and agreed it was doable.

I have learned the importance of writing unit tests for each component/function before writing the code. I realized that if you write the tests first, you can pretty much guarantee that that specific unit of code will do as expected. Now for making sure that each ‘unit’ of code will work together, that’s was integration tests are for.

One of the most important things I’ve learned is how to prioritize which parts of the codebase need priority coverage. There are different parts of the application that hold priority over others, because of this I learned that I should prioritize stricter test coverage for those specific ‘units’ of the codebase. Of course, striving for 90% — 100% test coverage is always the goal, sometimes when deadlines are on the horizon testing the critical pieces of the application is the best you can do.

Furthermore, I have also learned how to write YAML for Swagger documentation and will cover my experience with that next week.

At the end of the week i learned that the reason I was writing getting continual errors with the Unit Tests was because out of habit I was adding curly braces to my code:

jest.mock(“/path/to/middleware.js”, () => {
jest.fn((req, res, next) => next());
});

The error I was getting seemed completely unrelated to that specific line of code though

Jest Error

When googling everything I found related to that error, specifically said the error was caused by not exporting your modules correctly in your routes. But I knew I’d done that correctly or the routes wouldn’t work in the application. I checked anyways and they worked.

Once again, I sought out the help of my colleagues and within a few hours one of my colleagues pointed out I needed to add a return statement to my code

jest.mock(“/path/to/middleware.js”, () => {
return jest.fn((req, res, next) => next());
});

I was using the tests I had written on an old project that I used the same boilerplate middleware and was using the test files as a place to start. I realized upon inspection to see why the old code worked but my new code didn’t and i saw that i had confused myself because the code was formatted like this:

jest.mock(“/path/to/middleware.js”, () => 
jest.fn((req, res, next) => next());
);

As you can see this is valid code but at first glance it looks like this is “2 lines of code” when really its a one liner and there’s no return statement because the ES6 fat arrow functions have an implicit return when the following code is not in enclosed in curly brackets.

Out of habit I added the curly brackets to my code not realizing that it wasn’t on the old code and that’s what was causing the error.

--

--