Using Jest I've mockimplemented the method and testcase is getting succeeded and for testcase2 I need to implement same mock method with different input and I'm unable to do that.
jest.mock('../../lib/testService', () => ({
TestService : jest.fn(() => ({
callAPIProd: jest.fn().mockImplementation(() => Promise.resolve([{ DateTime: '2022-01-01'}])),
getAuthToken: jest.fn().mockImplementation(() => Promise.resolve({ data: 'mock token' })),
checkIfExistsInDB: jest.fn().mockImplementation(() => Promise.resolve(false)),
})),
}));
describe('getRates', () => {
it('should insert rates into DB if not already available', async () => {
// Arrange
const req = {} as Request;
const res = {
send: jest.fn(),
} as unknown as Response;
// Act
await integration.getRates(req, res);
// Assert
expect(res.send).toHaveBeenCalledWith('New Rates Received');
});
it('should send response if rates are already available in DB', async () => {
// Arrange
const req = {} as Request;
const res = {
send: jest.fn(),
} as unknown as Response;
// Act
await integration.getRates(req, res);
// Assert
expect(res.send).toHaveBeenCalledWith('Rates already available in DB');
});
});
In my getRates method I'm calling the "checkIfExistsInDB" service method which ret=turns true/false. First testcase is getting succeeded as I've mocked the implementation with false value. I want to clear the mockimplementation and set new mockimplementation with true value. How to achieve that?
Tried by re-defining the mock implementation in specific testcase
it('should send response if rates are already available in DB', async () => {
// Arrange
const req = {} as Request;
const res = {
send: jest.fn(),
} as unknown as Response;
//#1 - Tried to re-define in this way but it didn't work it's still taking value as false
jest.mock('../../lib/testService', () => ({
TestService : jest.fn(() => ({
callAPIProd: jest.fn().mockImplementation(() => Promise.resolve([{ DateTime: '2022-01-01'}])),
getAuthToken: jest.fn().mockImplementation(() => Promise.resolve({ data: 'mock token' })),
checkIfExistsInDB: jest.fn().mockImplementation(() => Promise.resolve(true)),
})),
}));
//#2 - Tried to re-define in this way but it didn't work it's still taking value as false
TestService.prototype.checkIfExistsInDB = jest.fn().mockImplementation(() => Promise.resolve(true));
// Act
await integration.getRates(req, res);
// Assert
expect(res.send).toHaveBeenCalledWith('Rates already available in DB');
});
jest.mock
at top level is hoisted, this is the way it affects import
statement. jest.mock
inside a test would result in implications, the whole module graph needs to be reimported inside a test, like this.
Mocking TestService.prototype.checkIfExistsInDB
won't work because TestService
is mocked function and doesn't deal with prototypes. In order to access checkIfExistsInDB
in tests it needs to be exposed in the scope of test suite. Adding an import similarly to mockGetName
in this example allows to avoid possible race conditions caused by jest.mock
hoisting:
import { mockedCheckIfExistsInDB } from '../../lib/testService'
jest.mock('../../lib/testService', () => {
const mockedCheckIfExistsInDB = jest.fn();
return {
__esModule: true,
mockedCheckIfExistsInDB,
TestService : jest.fn(() => ({
...
checkIfExistsInDB: mockedCheckIfExistsInDB,
})
};
});
beforeEach(() => {
mockedCheckIfExistsInDB.mockResolvedValue(false)
});
it('...', async () => {
...
mockedCheckIfExistsInDB.mockResolvedValue(true)
...
});
A test that redefines checkIfExistsInDB
mocked value shouldn't affect other tests, but this will happen if default mocked value is defined in jest.mock
. It needs to be defined before each test instead.