Table of Contents
The Test Results
Putting It Together
Running the Tests in the Browser
Running the Tests on Node
What’s Next?
Frequently Asked Questions on Unit Testing JavaScript with Mocha and Chai
How do I install Mocha and Chai for unit testing in JavaScript?
How do I write a basic test using Mocha and Chai?
How can I run my Mocha tests?
What are the different assertion styles available in Chai?
How can I test asynchronous code with Mocha and Chai?
How can I use hooks in Mocha?
How can I test exceptions with Chai?
How can I use spies, stubs, and mocks with Mocha and Chai?
How can I generate test reports with Mocha?
How can I make my tests more readable with Chai?
Home Web Front-end JS Tutorial Unit Test Your JavaScript Using Mocha and Chai

Unit Test Your JavaScript Using Mocha and Chai

Feb 16, 2025 am 11:03 AM

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

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1664
14
PHP Tutorial
1268
29
C# Tutorial
1246
24
The Evolution of JavaScript: Current Trends and Future Prospects The Evolution of JavaScript: Current Trends and Future Prospects Apr 10, 2025 am 09:33 AM

The latest trends in JavaScript include the rise of TypeScript, the popularity of modern frameworks and libraries, and the application of WebAssembly. Future prospects cover more powerful type systems, the development of server-side JavaScript, the expansion of artificial intelligence and machine learning, and the potential of IoT and edge computing.

JavaScript Engines: Comparing Implementations JavaScript Engines: Comparing Implementations Apr 13, 2025 am 12:05 AM

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

Python vs. JavaScript: The Learning Curve and Ease of Use Python vs. JavaScript: The Learning Curve and Ease of Use Apr 16, 2025 am 12:12 AM

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

JavaScript: Exploring the Versatility of a Web Language JavaScript: Exploring the Versatility of a Web Language Apr 11, 2025 am 12:01 AM

JavaScript is the core language of modern web development and is widely used for its diversity and flexibility. 1) Front-end development: build dynamic web pages and single-page applications through DOM operations and modern frameworks (such as React, Vue.js, Angular). 2) Server-side development: Node.js uses a non-blocking I/O model to handle high concurrency and real-time applications. 3) Mobile and desktop application development: cross-platform development is realized through ReactNative and Electron to improve development efficiency.

How to Build a Multi-Tenant SaaS Application with Next.js (Frontend Integration) How to Build a Multi-Tenant SaaS Application with Next.js (Frontend Integration) Apr 11, 2025 am 08:22 AM

This article demonstrates frontend integration with a backend secured by Permit, building a functional EdTech SaaS application using Next.js. The frontend fetches user permissions to control UI visibility and ensures API requests adhere to role-base

Building a Multi-Tenant SaaS Application with Next.js (Backend Integration) Building a Multi-Tenant SaaS Application with Next.js (Backend Integration) Apr 11, 2025 am 08:23 AM

I built a functional multi-tenant SaaS application (an EdTech app) with your everyday tech tool and you can do the same. First, what’s a multi-tenant SaaS application? Multi-tenant SaaS applications let you serve multiple customers from a sing

From C/C   to JavaScript: How It All Works From C/C to JavaScript: How It All Works Apr 14, 2025 am 12:05 AM

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

JavaScript and the Web: Core Functionality and Use Cases JavaScript and the Web: Core Functionality and Use Cases Apr 18, 2025 am 12:19 AM

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

See all articles