Testing
Setting up Jest with TypeScript
To keep thing clear and simple, we will move all the code related to the app to a new src
folder. For now, we just have index.ts
, but the number of files will quickly grow.
Create jest.config.js
in packages/api
with the following content:
Create setupTests.ts
and leave it empty. Anything in this file is run before the tests. We will need it later.
Now is also a good time to create our tsconfig.json
file in packages/api
.
Replace the content with the following:
Writing tests
There are 2 things that are notoriously difficult when unit testing:
Mocking imports
Testing asynchronous code
Let's write a function to fetch all the emojis available on GitHub.
First, install the required dependencies
Fetch the emojis:
Now we have a problem, how do we mock the request to GitHub? We don't want to send the request each time we run the test.
Mocking dependencies is hard
A lot of people struggle with setting up all the mocking required to isolate a function. They would end up writing a large amount of code to setup the test, but little to test the actual function.
Dependencies injection
Injecting dependencies allows us to arbitrarily set a dependency at any time. This is perfect for unit testing. We can also leverage some TypeScript functionalities around classes.
Let's get started:
Create a new file Emoji.ts
with a class Emoji
By using private readonly _fetch: typeof fetch = Container.get("fetch");
we can now set fetch
to anything we'd like.
Containers file
To avoid future mistake, we will create a containers.ts
file to list all the containers available and their type.
And we can now use it in our Emoji.ts
class
That's it. We can now mock anything, anywhere in our code.
Code coverage
If you run jest index.spec.ts --coverage
you will get a new folder src/coverage
Open coverage/index.html
in your browser.
Emoji.ts
has 100% code coverage. Let's add a if
statement and see what happens.
Run jest index.spec.ts --coverage
again
There are no tests going though this if
statement.
This is a fantastic tool to see how much of your code is tested.
Why do we even write test?
Some people struggle to understand why unit tests are useful. So why should we write test?
It is documentation
If anything, by reading the list of "it should..." someone can quickly get an understanding of what this class is about. This someone could be you in a few months.
If it can break, it will break
Sometimes we get distracted, we make mistakes and we break things. That's why it's important to have a few basic tests to automatically check if everything still does what it's supposed to do.
It can be part of the debugging process
Instead of restarting the server, sending a request and looking at the result, you can write a test. You can setup the scenario, call the function and assert the result. It speeds up the feedback loop.
Refactoring becomes easier
If you spot something you don't like and want to improve, go ahead. Assuming there's good coverage, if something breaks, tests will catch it.
To test or not to test
So people believe they must achieve 100% code coverage at all cost. While tests are great most of the time, writing tests for the sake of it is counter-productive. Test what makes sense. If something breaks, write a test so it doesn't happen again. With experience, you'll develop a sense for what needs to be tested and what doesn't.
The last thing you want to do is making your codebase more complex to test unimportant parts.
Test and/or mock when it makes sense.
Last updated
Was this helpful?