DEV Community

kjfossman
kjfossman

Posted on

Unit Testing in JS with Jest

Why does unit testing get overlooked at times? When we write code and something is not working we usually continue trying to fix it by manually testing our application until it shows us the results we want. Once it is working we are ready to move on and continue building something else or adding to the application. Some think "The effort of writing a test at this point is overkill and I just want to move on."

That may seem like a rational thought at the time. However if you plan to come back and work on this application in the future I recommend implementing some form of testing to help avoid bugs when refactoring. Imagine if someone else might work on this as well. The overall amount of time saved by writing tests is going to be worth it in the end.

To get started with writing your first test let's take on a very simple problem that we can later expand on. We will start with a sum function that takes in two arguments a & b.

We are going to use the Jest testing framework and this is what we need to get started.

Open up a new project in VScode and create a file called sum.js.

run the following commands to set up your test environment.

npm init -y

this will initialize with all the default values and is our starting point for package.json

{
  "name": "file_name_of_your_choice",
  "version": "1.0.0",
  "description": "",
  "main": "sum.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
Enter fullscreen mode Exit fullscreen mode

Then run

npm i --save-dev jest

This is saved as a development dependency because we only use the testing library in development.

You can see that it added the devDependencies

  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "jest": "^27.1.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now go into the package.json and change the test script to jest.

Was

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
Enter fullscreen mode Exit fullscreen mode

Now

"scripts": {
    "test": "jest"
  },
Enter fullscreen mode Exit fullscreen mode

run npm test and it will now run the tests

But none have been written!

Let's write our sum function in sum.js

const sum = (a,b) => {
    return a + b
}

module.exports = sum
Enter fullscreen mode Exit fullscreen mode

We have to export the sum function so that we can import it to our test file.

Create a file called

sum.test.js

This is naming convention to name your test file with the same name as the file that you are testing.

First we need to import sum and then we can write tests in sum.test.js.

Start with a simple test to determine if sum is a function. Pay attention to the syntax here.

const sum = require('./sum')

test('Check if sum is a function', () => {
    expect(typeof sum).toBe('function')
})
Enter fullscreen mode Exit fullscreen mode

Run npm test and you should see that you have 1 test passing.

The test we have written is labeled with whatever you write in parentheses and then expect typeof sum means that we are checking the constant sum type, and we expect it to be 'function' type. If we change 'function' to 'object' our test will fail.

Ok let's take it a step further and check if our sum function is properly adding two numbers. Directly below our first test we will write our second test.

test('Properly adds two numbers', () => {
    expect(sum(4,5)).toBe(9)
})
Enter fullscreen mode Exit fullscreen mode

Again run npm test and see that your tests pass.

To show an example of why testing is important make a simple addition to our file.

We want to create a function where we subtract the sum of our first function from a number we choose. It is going to look similar with just the two parameters passed in as seen here.

const subtractSum = (a, b) => {
    return a - b
}
Enter fullscreen mode Exit fullscreen mode

So that when we run

subtractSum(10, sum(4,5)) 
Enter fullscreen mode Exit fullscreen mode

We expect to get a return value of 1 and we do. So we should write a test to check this function. We need to change our import and export calls to this.

in the sum.js file

module.exports = {sum, subtractSum}
Enter fullscreen mode Exit fullscreen mode

in the sum.test.js file

const {sum, subtractSum} = require('./sum')
Enter fullscreen mode Exit fullscreen mode

Now we can write our test

test('Properly subtracts sum from number', () => {
    expect(subtractSum(10, sum(4,5))).toBe(1)
})
Enter fullscreen mode Exit fullscreen mode

All three tests are currently passing.

Now here is why the tests are important. You pass this application off to a friend who works on it. They come back to you and say that something is broken. This is what you have to look at without tests.

const sum = (a,b) => {
    return a * b 
}

const subtractSum = (a, b) => {
    return a - b
}
Enter fullscreen mode Exit fullscreen mode

Now figure out what is wrong. This is going to take some console.logging to check what returns you are getting when you run subtractSum(10, sum(4,5)) or whatever other ways you manually debug this.

But if you have tests you can just run your test suite and see where the errors are.

Run the tests and see two errors

Properly adds two numbers is failing
Properly subtracts sum from number is also failing

This tells me that we need to look into the properly adds two numbers test first. The second test relies on that one to pass so this seems easy enough.

Now there is a focused approach to our debugging and quickly find that your friend changed the '+' to a '*' in the sum function. Fix that and run the tests again. No problems now all tests are passing.

This is clearly a simple approach but even with something like this it begins to become very clear why testing in your applications is so important. If we didn't have these tests we might have been messing around with the subtractSum function for a while before realizing the root of the problem.

There is so much more you can do with the jest framework and the best way to learn is to try new things and work your way through some of these problems. In the end this will help you in your application building process.

Top comments (0)