(Updated: )
/ #node #jest #testing 

Mocking/stubbing ES6 classes in tests with examples of Sequelize model unit tests

Curious about Advanced Jest Testing Features?

Take your JavaScript testing to the next level by learning the ins and outs of Jest, the top JavaScript testing library.

Get "The Jest Handbook" (100 pages)

I want this

This post goes through some patterns that can be used to unit test ES6 classes.

The examples will use Jest module auto-mocking but should be portable to other module mocking libraries (eg. Proxyquire) with some modifications.

In “Using ES6 classes for Sequelize 4 models” we explored how to define Sequelize models using ES6 classes. One of the benefits of such an approach is that it allows easy unit testing, it allows you to instantiate the model without the baggage of all of Sequelize (and/or a database).

Table of Contents

We’ll be testing the following model (which is an ES6 class):

const { Model } = require('sequelize');

class MyModel extends Model {
  static init() {
    return super.init(
      // Config, see "Using ES6 classes for Sequelize 4 models"
    );
  }
  
  isAvailable (date) {
    if (!Array.isArray(this.meetings)) {
      throw new Error('meetings should be eager-loaded');
    }
    return !this.meetings.find(
      ({ startDate, endDate }) => (startDate < date && endDate > date)
    );
  }
}

module.exports = MyModel;

At the module level, we want to:

  • mock/stub out Sequelize (and the Model base class)
  • import the model

In the test:

  • Instantiate the model that we’ve defined (without crashing)
  • Set some properties on that instance
  • Run some methods
  • Assert on the output
jest.mock('sequelize');
const Model = require('./model');

test('It should not throw when passed a model containing an empty list of meetings', () => {
  const model = new Model();
  model.meetings = [];
  expect(model.isAvailable.bind(null, new Date(Date.now())).not.toThrow();
});

Alternative with Object.assign

If we’re setting more than a single instance property, using Object.assign can be easier to manage:

jest.mock('sequelize');

const Model = require('./model');

test('It should not throw when passed a model containing an empty list of meetings', () => {
  const model = Object.assign(
    new Model(),
    {
      meetings: []
    }
  );
  expect(model.isAvailable.bind(null, new Date(Date.now())).not.toThrow();
});

Using ES6 classes with Sequelize makes testing easier and more natural, sign up to the newsletter to stay in the loop for the upcoming Sequelize ES6 Cheat Sheet.

unsplash-logoElevate

Author

Hugo Di Francesco

Co-author of "Professional JavaScript", "Front-End Development Projects with Vue.js" with Packt, "The Jest Handbook" (self-published). Hugo runs the Code with Hugo website helping over 100,000 developers every month and holds an MEng in Mathematical Computation from University College London (UCL). He has used JavaScript extensively to create scalable and performant platforms at companies such as Canon, Elsevier and (currently) Eurostar.

Curious about Advanced Jest Testing Features?

Take your JavaScript testing to the next level by learning the ins and outs of Jest, the top JavaScript testing library. Get "The Jest Handbook" (100 pages)