Home > Web Front-end > JS Tutorial > Unit Test Your JavaScript Using Mocha and Chai

Unit Test Your JavaScript Using Mocha and Chai

尊渡假赌尊渡假赌尊渡假赌
Release: 2025-02-16 11:03:10
Original
911 people have browsed it

Unit Test Your JavaScript Using Mocha and Chai

Below:

<!-- load your test files here -->
Copy after login
Copy after login
Copy after login

Once you’ve added the script, you can then load the test runner page in your browser of choice.

The Test Results

When you run your tests, the test results will look something like this:

Unit Test Your JavaScript Using Mocha and Chai

Note that what we entered into the describe and it functions show up in the output — the tests are grouped under the description. Note that it’s also possible to nest describe blocks to create further sub-groupings.

Let’s take a look at what a failing test looks like.

On the line in the test that says:

assert.equal(arr.length, 0);
Copy after login
Copy after login
Copy after login

Replace the number 0 with 1. This makes the test fail, as the array’s length no longer matches the expected value.

If you run the tests again, you’ll see the failing test in red with a description of what went wrong.

Unit Test Your JavaScript Using Mocha and Chai

One of the benefits of tests is that they help you find bugs quicker, however this error is not very helpful in that respect. We can fix it though.

Most of the assertion functions can also take an optional message parameter. This is the message that is displayed when the assertion fails. It’s a good idea to use this parameter to make the error message easier to understand.

We can add a message to our assertion like so:

assert.equal(arr.length, 1, 'Array length was not 0');
Copy after login
Copy after login
Copy after login

If you re-run tests, the custom message will appear instead of the default.

Let’s switch the assertion back to the way it was — replace 1 with 0, and run the tests again to make sure they pass.

Putting It Together

So far we’ve looked at fairly simple examples. Let’s put what we’ve learned into practice and see how we would test a more realistic piece of code.

Here’s a function which adds a CSS class to an element. This should go in a new file js/className.js.

function addClass(el, newClass) {
  if(el.className.indexOf(newClass) === -1) {
    el.className += newClass;
  }
}
Copy after login
Copy after login
Copy after login

To make it a bit more interesting, I made it add a new class only when that class doesn’t exist in an element’s className property — who wants to see

after all?

In the best case, we would write tests for this function before we write the code. But test-driven development is a complex topic, and for now we just want to focus on writing tests.

To get started, let’s recall the basic idea behind unit tests: We give the function certain inputs and then verify the function behaves as expected. So what are the inputs and behaviors for this function?

Given an element and a class name:

  • if the element’s className property does not contain the class name, it should be added.
  • if the element’s className property does contain the class name, it should not be added.

Let’s translate these cases into two tests. In the test directory, create a new file classNameTest.js and add the following:

<!-- load your test files here -->
Copy after login
Copy after login
Copy after login

We changed the wording slightly to the “it should do X” form used with tests. This means that it reads a bit nicer, but is essentially still the same human-readable form we listed above. It’s usually not much more difficult than this to go from idea to test.

But wait, where are the test functions? Well, when we omit the second parameter to it, Mocha marks these tests as pending in the test results. This is a convenient way to set up a number of tests — kind of like a todo list of what you intend to write.

Let’s continue by implementing the first test.

assert.equal(arr.length, 0);
Copy after login
Copy after login
Copy after login

In this test, we create an element variable and pass it as a parameter to the addClass function, along with a string test-class (the new class to add). Then, we check the class is included in the value using an assertion.

Again, we went from our initial idea — given an element and a class name, it should be added into the class list — and translated it into code in a fairly straightforward manner.

Although this function is designed to work with DOM elements, we’re using a plain JS object here. Sometimes we can make use of JavaScript’s dynamic nature in this fashion to simplify our tests. If we didn’t do this, we would need to create an actual element and it would complicate our test code. As an additional benefit, since we don’t use DOM, we can also run this test within Node.js if we so wish.

Running the Tests in the Browser

To run the test in the browser, you’ll need to add className.js and classNameTest.js to the runner:

assert.equal(arr.length, 1, 'Array length was not 0');
Copy after login
Copy after login
Copy after login

You should now see one test pass and another test show up as pending, as is demonstrated by the following CodePen. Note that the code differs slightly from the example in order to make the code work within the CodePen environment.

See the Pen Unit Testing with Mocha (1) by SitePoint (@SitePoint) on CodePen.

Next, let’s implement the second test…

function addClass(el, newClass) {
  if(el.className.indexOf(newClass) === -1) {
    el.className += newClass;
  }
}
Copy after login
Copy after login
Copy after login

It’s a good habit to run your tests often, so let’s check what happens if we run the tests now. As expected, they should pass.

Here’s another CodePen with the second test implemented.

See the Pen Unit Testing with Mocha (2) by SitePoint (@SitePoint) on CodePen.

But hang on! I actually tricked you a bit. There is a third behavior for this function which we haven’t considered. There is also a bug in the function — a fairly serious one. It’s only a three line function but did you notice it?

Let’s write one more test for the third behavior which exposes the bug as a bonus.

<!-- load your test files here -->
Copy after login
Copy after login
Copy after login

This time the test fails. You can see it in action in the following CodePen. The problem here is simple: CSS class names in elements should be separated by a space. However, our current implementation of addClass doesn’t add a space!

See the Pen Unit Testing with Mocha (3) by SitePoint (@SitePoint) on CodePen.

Let’s fix the function and make the test pass.

assert.equal(arr.length, 0);
Copy after login
Copy after login
Copy after login

And here’s a final CodePen with the fixed function and passing tests.

See the Pen Unit Testing with Mocha (4) by SitePoint (@SitePoint) on CodePen.

Running the Tests on Node

In Node, things are only visible to other things in the same file. As className.js and classNameTest.js are in different files, we need to find a way to expose one to the other. The standard way to do this is through the use of module.exports. If you need a refresher, you can read all about that here: Understanding module.exports and exports in Node.js

The code essentially stays the same, but is structured slightly differently:

assert.equal(arr.length, 1, 'Array length was not 0');
Copy after login
Copy after login
Copy after login
function addClass(el, newClass) {
  if(el.className.indexOf(newClass) === -1) {
    el.className += newClass;
  }
}
Copy after login
Copy after login
Copy after login

And as you can see, the tests pass.

Unit Test Your JavaScript Using Mocha and Chai

What’s Next?

As you can see, testing does not have to be complicated or difficult. Just as with other aspects of writing JavaScript apps, you have some basic patterns which repeat. Once you get familiar with those, you can keep using them again and again.

But this is just scratching the surface. There’s a lot more to learn about unit testing.

  • Testing more complex systems
  • How to deal with Ajax, databases, and other “external” things?
  • Test-Driven Development

If you want to continue learning this and more, I’ve created a free JavaScript unit testing quickstart series. If you found this article useful, you should definitely check it out here.

Alternatively, if video is more your style, you might be interested in SitePoint Premium’s course: Test-Driven Development in Node.js.

Frequently Asked Questions on Unit Testing JavaScript with Mocha and Chai

How do I install Mocha and Chai for unit testing in JavaScript?

To install Mocha and Chai, you need to have Node.js and npm installed on your system. Once you have these, you can install Mocha and Chai using npm. Open your terminal and navigate to your project directory. Then, run the following commands:

npm install --save-dev mocha chai

This command installs Mocha and Chai as devDependencies for your project. The --save-dev flag is used to add these as development dependencies in your package.json file.

How do I write a basic test using Mocha and Chai?

Writing a basic test with Mocha and Chai involves creating a test file and writing your test cases in it. Here’s a simple example:

var expect = require('chai').expect;

describe('Basic Mocha String Test', function () {
it('should return number of charachters in a string', function () {
expect('Hello').to.have.lengthOf(5);
});
});

In this example, describe is a test suite that groups related tests, and it is a test case. The expect function from Chai is used to assert the expected output.

How can I run my Mocha tests?

To run your Mocha tests, navigate to your project directory in the terminal and run the following command:

./node_modules/.bin/mocha

This command runs the Mocha binary installed in your node_modules folder. If you want to run this command simply as mocha, you can install Mocha globally using npm install -g mocha.

What are the different assertion styles available in Chai?

Chai provides three different assertion styles – Should, Expect, and Assert. The Should style extends each object with a should property to start your chain. The Expect style provides a more traditional, function-based approach. The Assert style provides a classic, simple way to write assertions.

How can I test asynchronous code with Mocha and Chai?

Mocha and Chai provide several ways to test asynchronous code. You can use callbacks, Promises, or async/await. Here’s an example using async/await:

it('async test', async function() {
const result = await myAsyncFunction();
expect(result).to.equal(expectedResult);
});

In this example, myAsyncFunction is an asynchronous function that returns a Promise. The await keyword is used to wait for the Promise to resolve before continuing with the test.

How can I use hooks in Mocha?

Mocha provides hooks like before, after, beforeEach, and afterEach that you can use to set up preconditions and clean up after your tests. Here’s an example:

describe('hooks', function() {
before(function() {
// runs once before the first test in this block
});

after(function() {
// runs once after the last test in this block
});

beforeEach(function() {
// runs before each test in this block
});

afterEach(function() {
// runs after each test in this block
});
});

How can I test exceptions with Chai?

Chai provides the throw assertion for testing exceptions. Here’s an example:

it('throws an error', function() {
expect(function() { throw new Error('Wrong value'); }).to.throw('Wrong value');
});

In this example, the function passed to expect throws an error. The throw assertion is used to assert that the function throws an error with the message ‘Wrong value’.

How can I use spies, stubs, and mocks with Mocha and Chai?

To use spies, stubs, and mocks with Mocha and Chai, you can use a library like Sinon.js. Sinon.js can be easily integrated with Mocha and Chai to provide these functionalities.

How can I generate test reports with Mocha?

Mocha supports several reporters out of the box, including spec, dot, nyan, and more. You can specify the reporter to use with the --reporter option when running your tests. For example, mocha --reporter nyan.

How can I make my tests more readable with Chai?

Chai provides a chainable language to construct your assertions, making your tests more readable. For example, instead of writing expect(myVar).to.be.true;, you can write expect(myVar).to.be.true;. This makes your tests more natural and easier to understand.

The above is the detailed content of Unit Test Your JavaScript Using Mocha and Chai. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template