Mocha vs Jasmine in 2018: A side-by-side comparison

It’s official: JavaScript is everywhere.

JavaScript has been enabling browsers for years. NodeJS brought it to the server side. TypeScript has wrapped familiar object-oriented, statically-typed syntax around it. Anywhere you look, you’ll find JavaScript; on the client, server, mobile, and embedded systems.

All good software must be tested, and software written in JavaScript is no exception (pun intended.) Most JavaScript unit testing frameworks offer features such as:

  • Test runners
  • BDD-style test suites
  • Assertions
  • Spies
  • Fakes

Today, we’ll look at Mocha vs Jasmine.

Mocha vs Jasmine

Let’s take look at a quick overview of Jasmine and Mocha, with an eye toward their similarities and differences.

Jasmine was created around 2008. The documentation describes Jasmine as “batteries included,” meaning that it attempts to provide everything a developer needs in a test framework.

Mocha is younger than Jasmine, created around 2011. Mocha is not a “complete” test framework, and doesn’t attempt to be. Instead, Mocha covers the basics, and allows developers to extend it with other frameworks.

Common Ground: BDD Tests

At their core, Mocha and Jasmine both offer Behavior-Driven Design (BDD) tests:

describe("My First Test Suite", function() {
     it("introduces a test suite", function() {
       //assertion here
     });
   });

This is what Mocha vs Jasmine have in common. The describe function defines a test suite. The it function implements the BDD method of describing the behavior that a function should exhibit. The first parameter is a plain-English description of the behavior under test. The second parameter is a function that will call assertions that will pass or fail, depending on whether the described behavior was, or was not confirmed. A single describe test suite can embed multiple calls to the it function.

The implementations of Mocha and Jasmine diverge beyond this point. Now let’s take a look at their differences.

Mocha vs Jasmine: The main differences

Assertions Assertions are boolean functions that are used to test behavior. Typically, a true result indicates that a test passed, indicating that the expected behavior is what actually occurred when the test was run.

Jasmine includes an assertion library that uses an expect-style syntax:


View Codepen

describe("My First Test Suite", function() {
          it("introduces a test suite", function() {
            expect(true).toBe(true);
          });
        });  

Mocha does not have a built-in assertion library. Developers must use a dedicated assertion library in combination with Mocha. The popular Chai assertion library uses a syntax similar to Jasmine:


View Codepen

describe("My First Test Suite", function() {
      it("introduces a test suite", function() {
        expect(true).to.equal(true);
      });
    });

Chai uses a “fluent” syntax, where comparison operators can be chained together:

expect(foo).to.equal('foo')	     	//equality
expect(foo).to.not.equal('foo')	    //inequality
expect(foo).to.be.a('string')   	//type assertion

Chai also supports should-style and “classical” assert assertions.

Test Doubles / Spies Test double frameworks create test doubles. A test double, or spy, is like a clone of an object. A test double has the same functions as the original object, however, those functions are “stubbed out,” meaning that they don’t do anything. The “stubbed” functions exist so the test double framework can “watch” the double, tracking the calls to its functions.

Jasmine includes a spyOn method that can be used to create spies:

View Codepen

describe("Spying on an object", function(){
  var car, go = null;

  //the beforeEach setup function will be called with each run of the suite
  beforeEach(function(){
    car = {
      go: function(value) {
        speed = value;
      }
    };
    spyOn(car, 'go');	//creates the spy

    car.go(50);
    car.go(80);
  });

  //This test will succeed
  it("Called the go function", function(){
    expect(car.go).toHaveBeenCalled();
  });

  //This test will fail- the go function is called twice
  it("Called the go function once", function(){
    expect(car.go).toHaveBeenCalledTimes(1);
  });
});

Once again, Mocha does not include a spy framework. The SinonJS framework is a popular choice for creating spies:

View Codepen

describe("Spying on an object", function(){
  var car, go = null;

  //the beforeEach setup function will be called with each run of the suite
  beforeEach(function(){
    car = {
      go = function(value) {
        speed = value;
      }
    };
    sinon.spy(car, 'go');	//creates the spy

    car.go(50);
    car.go(80);
  });

  //This test will succeed
  it("Called the go function", function(){
    assert(car.go.called);
  });

  //This test will fail- the go function is called twice
  it("Called the go function once", function(){
    assert(car.go.calledOnce);
  });
});

The overall syntax between Jasmine and SinonJS are similar, however, there is a key difference. The Jasmine spy will not call the original “go” function by default. Only the spy “stub” is called unless .and.callThrough() is used when creating the spy:

spyOn(car, 'go').and.callThrough()

Sinon, however, will “pass through” the call to the implementation of the spied-on function by default.

Fake Server Test “fakes” are used to isolate a test from external dependencies. Unit tests should not make calls outside their scope to networks or databases. Fakes are used to simulate that behavior without actually making any external calls.

SinonJS is a more complete framework test double framework than Jasmine, including not only spies, but also stubs and fakes. Here is an example of a test using the SinonJS fake server:


View Codepen

before(function () { server = sinon.fakeServer.create(); });
after(function () { server.restore(); });

it("calls callback with deserialized data", function () {
  var callback = sinon.spy();
  getCustomer(5, callback);

  // This is part of the FakeXMLHttpRequest API
  server.requests[0].respond(
    200,
    { "Content-Type": "application/json" },
    JSON.stringify([{ id: 5, FirstName: "Bob", LastName: "Dobbs" }])
  );

  assert(callback.calledOnce);
});

Jasmine does not include fakes, so the Mocha + SinonJS option is best when you want to fake an HTTP server.

Which should I choose?

Jasmine comes included with assertions and spies, but that doesn’t necessarily make it the better option. Mocha does one thing, and does it well: BDD test definitions. Other best-of-breed frameworks combine with Mocha to extend it.

The best way to make your choice between Mocha vs Jasmine is to try both. Your particular needs, and the nature of the application under test, will make the better choice clear as you experiment. You can combine them, but to keep your tests consistent and readable, I recommend using Jasmine or Mocha+Chai+Sinon, within an application. Good luck!

Further reading

A full list of unit testing frameworks

Unit testing patterns: common patterns to follow for error-free software

The anatomy of robust unit testing