question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Having trouble figuring out how to mock Model with Jest

See original GitHub issue

I’m having trouble figuring out how I would mock Agreement.query().where().where() in a proper way. Here is the code with two models, Agreement and AgreementHistory.

const { Model, snakeCaseMappers } = require('objection');
const knex = require('knex')({
  client: 'postgresql',
  connection: process.env.MY_CONNECTION_STRING
});
Model.knex(knex);

class Agreement extends Model {
  static get tableName() {
    return 'agreement';
  }

  static get idColumn() {
    return 'agreement_id';
  }

  static get columnNameMappers() {
    return snakeCaseMappers();
  }
}

const getAgreements = async (filterOptions = {}) => {
  const { customerId, status } = filterOptions;
  const query = Agreement
    .query()
    .where({ customer_id: parseInt(customerId) });

  if (status) {
    query.where({ status: status });
  }

  return await query;
};

module.exports =  {
  getAgreements
};

/__mocks__/agreement.js

const mock = {
  query: jest.fn().mockReturnThis(),
  where: jest.fn().mockImplementation(() => {
    return {
      where: jest.fn().mockReturnValue('Hello World')
    }
  })
};
module.exports = mock;

The above mock could get ugly really fast if there are n-many where() calls. It’s a bit confusing because Objection allows the nice chaining syntax, but I am insure how I would create the mocks in Jest to support this.

Test File.

jest.mock('../models/agreement');
const Agreement = require('../models/agreement');

const repository = require('../agreementRepository');
  describe('getAgreements', () => {
    it.only('should allow filtering by customerId and status (if provided)', async () => {
      const results = await repository.getAgreements({ customerId: 555, status: 'Accepted' });
      expect(Agreement.query).toHaveBeenCalled(); // This test passes
      expect(results).toEqual('Hello World'); // This one fails. Error output below
    });
});

Error output from test above

Expected: "Hello World"
Received: {"where": [Function mockConstructor]}

Please let me know if this should be posted in the Jest issues page instead. Thanks.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5

github_iconTop GitHub Comments

1reaction
koskimascommented, Feb 26, 2021

@armandAkop You need to mock the prototype of the QueryBuilder class. Jest probably has examples of that

0reactions
armandAkopcommented, Feb 26, 2021

We ended up creating a “BaseModel” class which extends Model, then in our mocks we did this

let returnValue = null;

class BaseModel {};

/**
 * Sets return value on thenable module.
 * @param {*} value 
 */
BaseModel.mockReturnValue = (value) => {
    returnValue = value;
};

BaseModel.query = jest.fn().mockReturnThis();
BaseModel.insert = jest.fn().mockReturnThis();
BaseModel.insertGraphAndFetch = jest.fn().mockReturnThis();
BaseModel.insertGraph = jest.fn().mockReturnThis();
BaseModel.returning = jest.fn().mockReturnThis();
BaseModel.where = jest.fn().mockReturnThis();
BaseModel.withGraphFetched = jest.fn().mockReturnThis();
BaseModel.findById = jest.fn().mockReturnThis();
BaseModel.modifiers = jest.fn().mockReturnThis();
BaseModel.orderBy = jest.fn().mockReturnThis();
BaseModel.startTransaction = jest.fn();
BaseModel.then = jest.fn((done) => { done(returnValue); });

module.exports = BaseModel;

And this seemed to work fine for our case.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Manual Mocks - Jest
Manual mocks are used to stub out functionality with mock data. ... For example, to mock a module called user in the models...
Read more >
Understanding Jest Mocks. Explaining the Mock Function…
Mocking is a technique to isolate test subjects by replacing dependencies with objects that you can control and inspect.
Read more >
Cannot mock a module with jest, and test function calls
In my unit tests, I want to check that the method search was called with the correct arguments. My tests look something like...
Read more >
Mocking a JavaScript Class with Jest, two ways to make it easier
A guide on how to mock a JavaScript class using Jest, comparing dependency injection and mocking, along with guides on how to implement ......
Read more >
The only 3 steps you need to mock an API call in Jest
Alright, here it is. This is the big secret that would have saved me mountains of time as I was wrestling with learning...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found