I have a node module which exports a few classes, one of which is Client
, which I use to create a client (having a few APIs as methods).
I’m trying to test my module which uses this node module as a dependency using Jest. However, I’ve been unable to successfully mock the one method (say search()
) in the Client class.
Here is my spec for myModule
:
//index.spec.ts import * as nock from 'nock'; import * as externalModule from 'node-module-name'; import { createClient } from './../../src/myModule'; describe(() => { beforeAll(() => { nock.disableNetConnect(); }); it('test search method in my module', () => { jest.mock('node-module-name'); const mockedClient = <jest.Mock<externalModule.Client>>externalModule.Client; const myClient = createClient({/*params*/}); //returns instance of Client class present in node module by executing Client() constructor myClient.searchByName('abc'); //calls search API - I need to track calls to this API expect(mockedClient).toHaveBeenCalled(); expect(mockedClient.prototype.search).toHaveBeenCalledWith('abc'); }); });
This, however, doesn’t create a mock at all and triggers a nock error since the search API tries to connect to the url (given through params).
I’ve also tried mocking the Client class like the following. While successfully creating a mock for the Client class and also the search API (verified that search()
is also mocked through console logs), it gives me an error while I try to check if search()
has been called.
externalModule.Client = jest.fn(() => { return { search: jest.fn(() => Promise.resolve('some response')) } }); //creates the mock successfully, but not sure how to track calls to 'search' property const client = myModule.createClient(/*params*/); client.searchByName('abc'); expect(externalModule.Client).toHaveBeenCalled(); //Successful expect(externalModule.Client.prototype.search).toHaveBeenCalled(); //returns error saying "jest.fn() value must be a mock function or spy, Received: undefined"
I’m not sure what I’m doing wrong. Thank you in advance.
Advertisement
Answer
Mocking whole module
Try moving jest.mock
to the top of file
//index.spec.ts const search = jest.fn(); jest.mock('node-module-name', () => ({ Client: jest.fn(() => ({ search })) })); import * as nock from 'nock'; import * as externalModule from 'node-module-name'; import { createClient } from './../../src/myModule'; describe(() => { beforeAll(() => { nock.disableNetConnect(); }); it('test search method in my module', () => { const myClient = createClient({/*params*/}); myClient.searchByName('abc'); expect(externalModule.Client).toHaveBeenCalled(); expect(search).toHaveBeenCalledWith('abc'); externalModule.Client.mockClear(); search.mockClear(); }); });
Mocking only Client
Create search
constant and track it.
const search = jest.fn(); externalModule.Client = jest.fn(() => ({ search })); const client = myModule.createClient(/*params*/); client.searchByName('abc'); expect(externalModule.Client).toHaveBeenCalled(); expect(search).toHaveBeenCalled();