5
votes

I'm having trouble trying to mock a module with a constructor

// code.js
const ServiceClass = require('service-library');
const serviceInstance = new ServiceClass('some param');
exports.myFunction = () => {
  serviceInstance.doSomething();
};

And the test code:

// code.test.js
const ServiceClass = require('service-library');
jest.mock('service-library');
const {myFunction} = require('../path/to/my/code');

test('check that the service does something', () => {
  // ????
});

It's not like the Documentation example Mocking Modules because you need to instantiate the module after importing it. And isn't either like Mocking a Function.

How could I mock this doSomething() function while testing?

For reference, I'm trying to mock @google-cloud/* packages here. And I have a few projects that could take advantage on this.

2

2 Answers

8
votes

You need to mock the whole module first so that returns a jest mock. Then import into your test and set the mock to a function that returns an object holding the spy for doSomething. For the test there is difference between of a class called with new and a function called with new.

import ServiceLibrary from 'service-library'

jest.mock( 'service-library', () => jest.fn())

const doSomething = jest.fn()
ServiceLibrary.mockImplementation(() => ({doSomething}))
4
votes

Following @andreas-köberle solution I was able to mock @google-cloud/bigquery like so:

// mock bigquery library
const BigQuery = require('@google-cloud/bigquery');
jest.mock('@google-cloud/bigquery', () => jest.fn());
const load = jest.fn(() => ({'@type': 'bigquery#load_job'}));
const table = jest.fn(() => ({load}));
const dataset = jest.fn(() => ({table}));
BigQuery.mockImplementation(() => ({dataset}));

// mock cloud storage library
const {Storage} = require('@google-cloud/storage');
jest.mock('@google-cloud/storage');
const file = jest.fn(name => ({'@type': 'storage#file', name}));
const bucket = jest.fn(() => ({file}));
Storage.mockImplementation(() => ({bucket}));

I'm leaving this here as a reference in case someone else googles something similar. But to make it clear, thats just a particularization for @andreas-köberle answer