Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Facebook Unveils Jest for JavaScript Unit Testing, Automatic Mocking

Facebook Unveils Jest for JavaScript Unit Testing, Automatic Mocking

Lire ce contenu en français

Facebook has released Jest, an open source Unit Testing tool for JavaScript, built on top of Jasmine.

Jest was originally conceived by Facebook two years ago as a way to solve the need for writing fast, reliable tests for the web chat application. As it gained interest internally the project was picked up six months ago by Jeff Morrison, a software engineer for Facebook, who set out to make performance improvements and take Jest open source.

At its most basic level, Jest is designed to make it faster and easier to write idiomatic JavaScript tests. Jest automatically mocks CommonJS modules returned by require(), and other features include built-in support for DOM APIs in test environments, sensible defaults, support for pre-processing code, and parallel test execution by default. By running tests concurrently in parallel processes, Jest has test runs finish sooner.

Morrison said:

The goal for Jest is to reduce the time spent and cognitive load necessary to get started with testing a project -- and so it provides most of the things you need out of the box: A fast CLI, a set of mocking utilities, and its automatic module mocking system.

Additionally, if you're looking for isolation tools like mocking libraries, most other tools will leave you writing quite an unsatisfactory bit of boilerplate in your tests (and often even in your main code) just to get going.

We've seen first-hand at Facebook how important it is to spend more time writing your app (vs time spent getting set up to write your app) -- and so this is the problem Jest is focused on solving.

Jest differs from the Jasmine framework by adding several layers on top. Most notably, Jest automatically mocks dependencies when running tests. Jest automatically generates mocks for each of a module's depenedencies, and provides those mock by default -- making it easier to isolate a module from its dependencies. Morrison said that isolation is the default for new tests, and developers would now have "complete control" over how much isolation is needed. Each test indicates which modules should or should not be mocked.

Facebook's documentation goes into further detail on Automatic Mocking:

Jest actually implements its own version of the require() function in the testing environment. Jest's custom require() function loads the real module, inspects what it looks like, and then makes a mocked version based on what it saw and returns that.

This means Jest is going to give you an object with the same shape as the real module, but with mocks for each of the exported values instead of the real values.

Although Jest introduces automatic mocking, it is also noted that it is still possible for developers to control what is and is not mocked by providing jest.mock() and jest.dontMock() APIs for customization.

Reaction from the community was mostly positive. On Hacker News, user Cthulu said:

Looks interesting: the test suite for our current AngularJS project is slowly slowing down, in part because there's just more tests, but the major performance bottlenecks are:
  • No parallelisation, even if test suites are all independent
  • DOM tests, which cause a lot of GC pauses
  • (Probably) PhantomJS startup and initialisation (not measured)
I've done a simple optimization where my tests get split in the middle and run in two separate terminals (during development, continuous testing), but it's kinda iffy.

Directly addressing dependency injection and AngularJS, Facebook says "Jest achieves the same result using a different approach." With Angular, code is written by passing dependencies as arguments, making it very easy to write a test. However, Facebook notes that in order to have a testable function in Angular, developers conform to its specific pattern and pass it into Angular's dependency injection framework. The solution in Jest is slightly different:

Jest allows for mocking dependencies in the same way that Angular does, but instead of building a proprietary module loader, it uses CommonJS. This enables you to test any existing code that already uses CommonJS without having to heavily refactor it to make it compatible with another module system.

User Caiob agreed with the positive sentiment about Jest and was a fan of the approach to dependency injection, saying: "It's great that Facebook are improving an existing/familiar tool like Jasmine. Also, I love the way they treat CommonJS modules."

With Jest, Morrison says Facebook want to start of a trend toward making testing easy, leaving developers more time to writing their app. InfoQ readers who would like to contribute to the project can check out the github repo and send pull requests, or join in #jestjs on freenode.

Rate this Article