DEV Community


Posted on • Originally published at

How to migrate from Mocha to Jest

Jest is a simple testing library that works with zero configuration. Because of its great API - if you're already using Mocha - with a few find & replace and minimal effort, you can move to Jest without rewriting any of your tests.

In this post, I'll show you how I tweaked my existing Mocha setup to achieve this.

If you're new to Jest, don't forget to check out their Getting Started page as well.

I personally got hooked on this library when I realized it comes with a configuration option testEnvironment, that gives you a test environment with a JSDOM that works out of the box, without actually configuring JSDOM. I've lost count, across all projects, how many times I wanted to update the testing environment and ended up not doing it because I couldn't get JSDOM to work with my existing tests.

Let's jump straight into it!


I use mocha.opts to configure Mocha. The contents of this file are important because I'm going to reference them later:

--reporter spec
--ui bdd
--file test_helpers/babel_loader.js
--file test_helpers/jsdom_setup.js
--file test_helpers/test_setup.js
Enter fullscreen mode Exit fullscreen mode

and this is how I used to run Mocha:

mocha --opts mocha.opts
Enter fullscreen mode Exit fullscreen mode

You can configure Jest with jest.config.js, a js or JSON file with the --config flag, and in package.json, see Configuring Jest. I suggest you start with package.json because I think that's the simplest. Once the configuration gets more complex, you can always move it into a separate file.
In package.json you should use the key "jest" on the top level, like this:

  "name": "my-project",
  "jest": {
    "verbose": true
Enter fullscreen mode Exit fullscreen mode

now you should be able to run Jest as:

Enter fullscreen mode Exit fullscreen mode


This is the only place where depending on what other libraries you use in your tests, you might want to tweak their setup a bit.

In my case, test_helpers/test_setup.js had the environment setup for Mocha.
If you're using Enzyme or Sinon for example, this is the place where you keep their configuration.
Let's say your file has something similar:

global.sinonSandbox = sinon.createSandbox();
afterEach(function() {
  return global.sinonSandbox.restore();
Enter fullscreen mode Exit fullscreen mode

Then you should be able to reuse this with Jest.

Jest does its environment setup with setupFilesAfterEnv.
This option tells the library which file(s) to run before each test. Put this into package.json after verbose:

  "name": "my-project",
  "jest": {
    "verbose": true,
    "setupFilesAfterEnv": ["<rootDir>/test_helpers/test_setup.js"]
Enter fullscreen mode Exit fullscreen mode

Side-note: this doesn't exactly match the behavior of the Mocha configuration. Instead of creating only one sandbox, now we create one sandbox before each test. However, there should be no difference in how Sinon interacts with your tests.


Mocha operates with a wide variety of hooks. I mostly used describe(), context(), it(), before(), after(), beforeEach(), and afterEach().

Jest uses a bit different naming, in general, you're safe to replace:

before ➡️ beforeAll

after ➡️ afterAll

context doesn't have an equivalent in Jest, so I decided to use describe.
You can find & replace all occurrences of context, before, and after or put the following code into test_helpers/test_setup.js:

// mocha keyword mappings
window.context = describe;
window.before = beforeAll;
window.after = afterAll;
Enter fullscreen mode Exit fullscreen mode

Function parameters

With Mocha, you were able to give hooks a description:

beforeEach(description, fn)
afterEach(description, fn)
Enter fullscreen mode Exit fullscreen mode

in Jest, hooks only accept a function and an optional timeout:

beforeEach(fn, timeout)
afterEach(fn, timeout)
Enter fullscreen mode Exit fullscreen mode

If your beforeEach blocks looked something like this:

beforeEach('login', () => {
Enter fullscreen mode Exit fullscreen mode

to strip out the descriptions from every beforeEach run the following regular expression in your editor:

Enter fullscreen mode Exit fullscreen mode

and replace it with

Enter fullscreen mode Exit fullscreen mode


We set up Babel in test_helpers/babel_loader.js for Mocha:

// Run before any test files are loaded to use Babel for subsequent parsing
  ignore: [/node_modules\//],
  extensions: ['.js', '.jsx', '.ts', '.tsx'],
Enter fullscreen mode Exit fullscreen mode

You have to install babel-jest to use Babel with Jest:

yarn add --dev babel-jest
Enter fullscreen mode Exit fullscreen mode

then add transfer to package.json that now should look like this:

  "name": "my-project",
  "jest": {
    "verbose": true,
    "setupFilesAfterEnv": ["<rootDir>/test_helpers/test_setup.js"],
    "transform": {
      "^.+\\.[t|j]sx?$": "babel-jest",
Enter fullscreen mode Exit fullscreen mode

See more on using Babel with Jest.

At this point, you're pretty much ready to run your existing tests with Jest.


What I really liked about Jest is the "work great by default" philosophy.

Even when installed in an empty package and run, it gives you a meaningful output:

% jest
No tests found, exiting with code 1
Run with `--passWithNoTests` to exit with code 0
In /Users/akoskm/Projects/test
  2 files checked.
  testMatch: **/__tests__/**/*.[jt]s?(x), **/?(*.)+(spec|test).[tj]s?(x) - 0 matches
  testPathIgnorePatterns: /node_modules/ - 2 matches
  testRegex:  - 0 matches
Pattern:  - 0 matches
Enter fullscreen mode Exit fullscreen mode

It doesn't ask for configuration files or necessary parameters, it simply works. I think this is a philosophy worth following when designing new tools.

What tools do you use to test your code?

Are you stuck in the middle of a migration? Let me know in the comments or find me on Twitter.

Top comments (0)