'Jest - how to mock function in initialised class instance
I have the following module:
import { MetadataStore } from 'metadata-store';
import { AttributeMap } from 'aws-sdk/clients/dynamodb';
const dataStore = new MetadataStore();
export async function getContentData(
dataIds: string[]
): Promise<AttributeMap[]> {
try {
return dataStore.getBatch(dataIds);
} catch (error) {
logger.error('getContentData error', error);
throw error;
}
}
I'm trying to mock the call to getBatch, but I get an error that dataStore is mock constructor and does not a getBatch defined.
This is my test file:
import { mocked } from 'ts-jest/utils';
import * as dataStoreSdk from 'metadata-store';
import { getContentData } from '../metaDataSdk';
jest.mock('metadata-store', () => {
return {
MetadataStore: jest.fn()
};
});
let getBatchMocked: jest.Mock;
describe('getContentData tests', () => {
beforeEach(() => {
getBatchMocked = jest.fn();
mocked(dataStoreSdk.MetadataStore).mockImplementation(() => {
return { getBatch: getBatchMocked } as unknown as dataStoreSdk.MetadataStore;
});
});
it('Should return successful response', async () => {
// eslint-disable-next-line @typescript-eslint/camelcase
getBatchMocked.mockResolvedValue({ is_deleted: true });
const response = await getContentData(['id_1']);
expect(response).toEqual(1);
expect(getBatchMocked.mock.calls.length).toEqual(1);
expect(getBatchMocked).toHaveBeenCalledWith(1);
});
});
another attempt which results in a different error:
import { mocked } from 'ts-jest/utils';
import * as dataStoreSdk from 'metadata-store';
import { getContentData } from '../metaDataSdk';
let getBatchMocked: jest.Mock = jest.fn();
jest.mock('metadata-store', () => {
return {
MetadataStore: {
getBatch: getBatchMocked
}
};
});
describe('getContentData tests', () => {
beforeEach(() => {
getBatchMocked = jest.fn();
mocked(dataStoreSdk.MetadataStore).mockImplementation(() => {
return { getBatch: getBatchMocked } as unknown as dataStoreSdk.MetadataStore;
});
});
it('Should return successful response', async () => {
// eslint-disable-next-line @typescript-eslint/camelcase
getBatchMocked.mockResolvedValue({ is_deleted: true });
const response = await getContentData(['id_1']);
expect(response).toEqual(1);
expect(getBatchMocked.mock.calls.length).toEqual(1);
expect(getBatchMocked).toHaveBeenCalledWith(1);
});
});
ReferenceError: Cannot access 'getBatchMocked' before initialization
Please advise how can I mock this module?
Solution 1:[1]
Typically to test this, you need to use dependency injection to send the data store into the class instead of creating a new instance. That way, you can mock the service, and have the return set there. The constructor would take the instance if using a class, or pass the object to your function.
export async function getContentData(dataStore: MetadataStore, dataIds: string[]): Promise<AttributeMap[]> {}
Then the test would have something like:
it('Should return successful response', async () => {
getBatchMocked.mockResolvedValue({ is_deleted: true });
const response = await getContentData(getBatchedMock, ['id_1']);
...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Steven Scott |
