Dave Stein
Dave Stein

Reputation: 9316

How can I instantiate a Sequelize model to be used in Unit Tests?

I am trying to write unit tests for a Sequelize model. I have an instance method on the class that call's Sequelize's update method. Turning update into a mocked function is no problem. I just can't seem to figure out how to properly do a X = new MyModel() without some kind of error. It tells me Class constructor model cannot be invoked without 'new'.

I took a look at https://sequelize-mock.readthedocs.io/en/stable/ but the way it's written makes me think it's better suited for mocking the Models when testing classes that are taking advantage of a model, rather than the model itself.

const BaseUtut = sequelizeInstance.define('utut', {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    autoIncrement: true
  },
  metadata: {
    type: Sequelize.JSON
  }
});

class Utut extends BaseUtut {
  async updateFromFlat(id, metadata) {

    // in reality, i modify metadata, and want to test things around that
    modifiedMetadata = methodThatModified(metadata);

    // I want to see that update is called with the right output of the modified metadata
    return await this.update(
      {
        id: id,
        metadata: modifiedMetadata
      },
      {
        where: {
          locale: metadata.locale
        }
      }
    );
  }
}

So with the above code sample, if I have an insance of Utut, I know I can easily mock update. I just don't know how to initialize the class to then mock things.

The intent of the test I want to write is simply to see that update is called with the right parameters, based on my own code that has nothing to do with Sequelize. I want to make sure my transform on the inputs are set right when going to Sequelize. I am not planning to check that the DB is actually updated. The only problem I am having is actually instantiating the model.

So all I need is for code like this to work:

const instance = new Utut(); // This line doesn't work
instance.update = Jest.fn();

I'm not sure why it says I need to invoke with new, when that is exactly what I am doing.

Upvotes: 1

Views: 1842

Answers (1)

Dave Stein
Dave Stein

Reputation: 9316

So taking advantage of the Model being returned from Sequelize.define causes this issue. Rather than doing class Utut extends BaseUtut {, I did this:

// Static methods
Object.assign(BaseUtut, {});
// Instance methods
Object.assign(BaseUtut.prototype, {});

Doing that lets me do new on the model with no issue in my tests

Update

Just saw this was unanswered on 9/23/19. The above answer looks to be for an older version. I now just do

class MyClass extends Sequelize.Model {}
MyClass.init(definition, options);
export default MyClass;

Upvotes: 1

Related Questions