I have the following jest test configuration for my collection of AWS JS Node Lambdas. I have a module called dynamoStore I reference in several different lambdas package.json and use within the lambdas. I am trying to get test one of these lambdas by mocking the dynamo store module as it makes calls to dynamoDb. The problem is that the jest.fn implementation never gets called. I confirmed this by sticking a breakpoint in that line as well as logging the value the calling methods returns from it.
When I check lambda1/index.js in the debugger getVehicleMetaKeysFromDeviceId() is a jest object but when it is called it doesn't use my mock implementation
How do I get this implementation to work? Have I set up my mock incorrectly?
dynamoStore/vehicleMetaConstraints
exports.getVehicleMetaKeysFromDeviceId= async (data) => {
return data
};
dynamoStore/index.js
exports.vehicleMetaConstraints = require("./vehicleMetaConstraints");
...
lambda1/index.js
const { vehicleMetaStore } = require("dynamo-store");
exports.handler = async (event, context, callback) => {
const message = event;
let vehicle_ids = await vehicleMetaStore.getVehicleMetaKeysFromDeviceId(message.id);
// vehicle_ids end up undefined when running the test
}
lambda1/index.test.js
const { vehicleMetaStore } = require("dynamo-store");
jest.mock("dynamo-store", () => {
return {
vehicleMetaStore: {
getVehicleMetaKeysFromDeviceId: jest.fn(),
},
};
});
describe("VehicleStorageLambda", () => {
beforeEach(() => {
jest.resetModules();
process.env = { ...env };
});
afterEach(() => {
jest.clearAllMocks();
});
test("Handles first time publish with existing device", async () => {
let functionHandler = require("./index");
vehicleMetaStore.getVehicleMetaKeysFromDeviceId.mockImplementationOnce(() =>
// This never gets called
Promise.resolve({
device_id: "333936303238510e00210022",
})
);
await functionHandler.handler({});
});
});
Remove the call to jest.resetModules() in beforeEach. That's re-importing your modules before each test, and wiping out your mocks.
https://stackoverflow.com/a/59792748/3084820
I'm trying to test a module that imports from another that has a weird export structure.
I'm using javascript with node, and jest for testing.
This is basically the code structure for the exports and the tests.
// weirdModule.js
module.exports = ({param1, param2}) = {
const weirdModuleFunction = async () => {
return await someIrrelevantFunction(param1, param2);
};
return async () => {
try {
return await weirdModuleFunction();
}
catch (e) {
throw e;
}
};
}
}
// testThisModule.js
const _weirdModuleFunction = require('weirdModule.js');
const testThisFunction = () => {
const weirdModuleFunction = _weirdModuleFunction({'abc',123});
let someDataIWantToBeMockedFromWeirdModule = await weirdModuleFunction();
const resultIWantToExpect = someDataIWantToBeMockedFromWeirdModule + ' someDataForExample';
return resultIWantToExpect;
};
module.exports = { testThisFunction }
//testThisModule.test.js
const { testThisFunction } = require('testThisModule.js');
//jest mocks to return different values for weirdModule.js
it('should return some value from weirdModule + someData',()=>{
//mockImplementation for weirdModule, maybe even mockImplementationOnce for successive testing
expect(testThisFunction()).toEqual('whatIexpect1 someDataForExample');
expect(testThisFunction()).toEqual('whatIexpectWithADifferentMockImplementation someDataForExample');
});
I'd like a solution that allows me to mock what weirdModule.js returns, and to also be able to mock it so it returns different values.
I have many tests for different branches, so I need to be able to change the mock return for weirdModule so I can have data that can be used across many tests, and some for some specific tests
I CANNOT change the structure of weirdModule (I didn't design it), and I CANNOT use anything other than jest, and I don't want to use manual mocks from __mocks__
I have managed to get it to work with only one return value, but I need to be able to change it to different values. It currently works like this:
jest.mock('weirdModule.js', () => () => {
return jest.fn(() => {
return 'whatIexpect1';
});
}
How can I achieve this? I've been scratching my head for days trying to have jest play nice and not throw 'weirdModuleFunction is not a function' when trying to mock different values for different tests. Any help is appreciated.
You need to capture weirdModule.js as a mock module in your test file. To do this, add these at the beginning of testThisModule.test.js
const weirdModule = require('weirdModule.js');
jest.mock('weirdModule.js');
Now you can mock the weird module however you want, like this:
it('should return some value from weirdModule + someData', async () => {
//mockImplementation for weirdModule, maybe even mockImplementationOnce for successive testing
weirdModule.mockImplementationOnce( () => {
return () => {
return 'whatIexpect1';
};
});
expect(await testThisFunction()).toEqual('whatIexpect1 someDataForExample');
weirdModule.mockImplementationOnce( () => {
return () => {
return 'whatIexpectWithADifferentMockImplementation';
};
});
expect(await testThisFunction()).toEqual('whatIexpectWithADifferentMockImplementation someDataForExample');
});
Hope this helps!
I want to mock the below line of code. And please explain how I can mock this in detail as I'm new to javascript and writing test cases. The below code would return a promise.
const createPriceConfiguration = (fastify, req) => {
return fastify.pg.transact(client => insertQuery(fastify, client, req));
};
const client = {
query: jest.fn(() => {
return new Promise(resolve => {
resolve({ rows: [req.body] });
});
})
};
My colleague gave a solution which I'm not able to understand.
transact: jest.fn(queryFunction => {
return queryFunction(client);
})
You want to test createPriceConfiguration function which takes fastify object and calls function from it. Mocking this function can be done by mocking the fastify object. You need to mock the transact method in the fastify object passed to return desired response (e.g. promise or result of an other function, ...)
const mockedFastify = {
pg: {
transact: jest.fn(() => new Promise(resolve => {
...desired code
}))
}
};
Then in test case You pass mocked object createPriceConfiguration(mockedFastify);
I'd like to change the implementation of a mocked dependency on a per single test basis by extending the default mock's behaviour and reverting it back to the original implementation when the next test executes.
More briefly, this is what I'm trying to achieve:
Mock dependency
Change/extend mock implementation in a single test
Revert back to original mock when next test executes
I'm currently using Jest v21. Here is what a typical test would look like:
// __mocks__/myModule.js
const myMockedModule = jest.genMockFromModule('../myModule');
myMockedModule.a = jest.fn(() => true);
myMockedModule.b = jest.fn(() => true);
export default myMockedModule;
// __tests__/myTest.js
import myMockedModule from '../myModule';
// Mock myModule
jest.mock('../myModule');
beforeEach(() => {
jest.clearAllMocks();
});
describe('MyTest', () => {
it('should test with default mock', () => {
myMockedModule.a(); // === true
myMockedModule.b(); // === true
});
it('should override myMockedModule.b mock result (and leave the other methods untouched)', () => {
// Extend change mock
myMockedModule.a(); // === true
myMockedModule.b(); // === 'overridden'
// Restore mock to original implementation with no side effects
});
it('should revert back to default myMockedModule mock', () => {
myMockedModule.a(); // === true
myMockedModule.b(); // === true
});
});
Here is what I've tried so far:
mockFn.mockImplementationOnce(fn)
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
myMockedModule.b.mockImplementationOnce(() => 'overridden');
myModule.a(); // === true
myModule.b(); // === 'overridden'
});
Pros
Reverts back to original implementation after first call
Cons
It breaks if the test calls b multiple times
It doesn't revert to original implementation until b is not called (leaking out in the next test)
jest.doMock(moduleName, factory, options)
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
jest.doMock('../myModule', () => {
return {
a: jest.fn(() => true,
b: jest.fn(() => 'overridden',
}
});
myModule.a(); // === true
myModule.b(); // === 'overridden'
});
Pros
Explicitly re-mocks on every test
Cons
Cannot define default mock implementation for all tests
Cannot extend default implementation forcing to re-declare each mocked method
Manual mocking with setter methods (as explained here)
// __mocks__/myModule.js
const myMockedModule = jest.genMockFromModule('../myModule');
let a = true;
let b = true;
myMockedModule.a = jest.fn(() => a);
myMockedModule.b = jest.fn(() => b);
myMockedModule.__setA = (value) => { a = value };
myMockedModule.__setB = (value) => { b = value };
myMockedModule.__reset = () => {
a = true;
b = true;
};
export default myMockedModule;
// __tests__/myTest.js
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
myModule.__setB('overridden');
myModule.a(); // === true
myModule.b(); // === 'overridden'
myModule.__reset();
});
Pros
Full control over mocked results
Cons
Lot of boilerplate code
Hard to maintain on long term
jest.spyOn(object, methodName)
beforeEach(() => {
jest.clearAllMocks();
jest.restoreAllMocks();
});
// Mock myModule
jest.mock('../myModule');
it('should override myModule.b mock result (and leave the other methods untouched)', () => {
const spy = jest.spyOn(myMockedModule, 'b').mockImplementation(() => 'overridden');
myMockedModule.a(); // === true
myMockedModule.b(); // === 'overridden'
// How to get back to original mocked value?
});
Cons
I can't revert mockImplementation back to the original mocked return value, therefore affecting the next tests
Use mockFn.mockImplementation(fn).
import { funcToMock } from './somewhere';
jest.mock('./somewhere');
beforeEach(() => {
funcToMock.mockImplementation(() => { /* default implementation */ });
// (funcToMock as jest.Mock)... in TS
});
test('case that needs a different implementation of funcToMock', () => {
funcToMock.mockImplementation(() => { /* implementation specific to this test */ });
// (funcToMock as jest.Mock)... in TS
// ...
});
A nice pattern for writing tests is to create a setup factory function that returns the data you need for testing the current module.
Below is some sample code following your second example although allows the provision of default and override values in a reusable way.
const spyReturns = returnValue => jest.fn(() => returnValue);
describe("scenario", () => {
beforeEach(() => {
jest.resetModules();
});
const setup = (mockOverrides) => {
const mockedFunctions = {
a: spyReturns(true),
b: spyReturns(true),
...mockOverrides
}
jest.doMock('../myModule', () => mockedFunctions)
return {
mockedModule: require('../myModule')
}
}
it("should return true for module a", () => {
const { mockedModule } = setup();
expect(mockedModule.a()).toEqual(true)
});
it("should return override for module a", () => {
const EXPECTED_VALUE = "override"
const { mockedModule } = setup({ a: spyReturns(EXPECTED_VALUE)});
expect(mockedModule.a()).toEqual(EXPECTED_VALUE)
});
});
It's important to say that you must reset modules that have been cached using jest.resetModules(). This can be done in beforeEach or a similar teardown function.
See jest object documentation for more info: https://jestjs.io/docs/jest-object.
Little late to the party, but if someone else is having issues with this.
We use TypeScript, ES6 and babel for react-native development.
We usually mock external NPM modules in the root __mocks__ directory.
I wanted to override a specific function of a module in the Auth class of aws-amplify for a specific test.
import { Auth } from 'aws-amplify';
import GetJwtToken from './GetJwtToken';
...
it('When idToken should return "123"', async () => {
const spy = jest.spyOn(Auth, 'currentSession').mockImplementation(() => ({
getIdToken: () => ({
getJwtToken: () => '123',
}),
}));
const result = await GetJwtToken();
expect(result).toBe('123');
spy.mockRestore();
});
Gist:
https://gist.github.com/thomashagstrom/e5bffe6c3e3acec592201b6892226af2
Tutorial:
https://medium.com/p/b4ac52a005d#19c5
When mocking a single method (when it's required to leave the rest of a class/module implementation intact) I discovered the following approach to be helpful to reset any implementation tweaks from individual tests.
I found this approach to be the concisest one, with no need to jest.mock something at the beginning of the file etc. You need just the code you see below to mock MyClass.methodName. Another advantage is that by default spyOn keeps the original method implementation but also saves all the stats (# of calls, arguments, results etc.) to test against, and keeping the default implementation is a must in some cases. So you have the flexibility to keep the default implementation or to change it with a simple addition of .mockImplementation as mentioned in the code below.
The code is in Typescript with comments highlighting the difference for JS (the difference is in one line, to be precise). Tested with Jest 26.6.
describe('test set', () => {
let mockedFn: jest.SpyInstance<void>; // void is the return value of the mocked function, change as necessary
// For plain JS use just: let mockedFn;
beforeEach(() => {
mockedFn = jest.spyOn(MyClass.prototype, 'methodName');
// Use the following instead if you need not to just spy but also to replace the default method implementation:
// mockedFn = jest.spyOn(MyClass.prototype, 'methodName').mockImplementation(() => {/*custom implementation*/});
});
afterEach(() => {
// Reset to the original method implementation (non-mocked) and clear all the mock data
mockedFn.mockRestore();
});
it('does first thing', () => {
/* Test with the default mock implementation */
});
it('does second thing', () => {
mockedFn.mockImplementation(() => {/*custom implementation just for this test*/});
/* Test utilising this custom mock implementation. It is reset after the test. */
});
it('does third thing', () => {
/* Another test with the default mock implementation */
});
});
I did not manage to define the mock inside the test itself so I discover that I could mock several results for the same service mock like this :
jest.mock("#/services/ApiService", () => {
return {
apiService: {
get: jest.fn()
.mockResolvedValueOnce({response: {value:"Value", label:"Test"}})
.mockResolvedValueOnce(null),
}
};
});
I hope it'll help someone :)
It's a very cool way I've discovered on this blog https://mikeborozdin.com/post/changing-jest-mocks-between-tests/
import { sayHello } from './say-hello';
import * as config from './config';
jest.mock('./config', () => ({
__esModule: true,
CAPITALIZE: null
}));
describe('say-hello', () => {
test('Capitalizes name if config requires that', () => {
config.CAPITALIZE = true;
expect(sayHello('john')).toBe('Hi, John');
});
test('does not capitalize name if config does not require that', () => {
config.CAPITALIZE = false;
expect(sayHello('john')).toBe('Hi, john');
});
});
I have a function that calls another function
const getArtist = (id) => {
// builds params for other function
return otherFuntion(params);
}
I want to verify that when I call getArtist(someValue), otherFunction gets called with the right arguments.
How can I accomplish that with jest ?
describe('getArtist function', () => {
it('should call otherFunction with the right params', () => {
// how can I get a handle on the mock of otherFunction to see
// if it was called correctly ?
});
});
You could use proxyquire to mock out the imported function at compile time if it's a public function. If it's a private function then you definitely don't want to mock it out.
You should probably just test the return value of otherFuntion instead.
So you are really calling the function otherFuntion(params) so I would rather check if return of your getArtist functions gives the same results as otherFunction called with right params.
describe('getArtist function', () => {
it('should call otherFunction with the right params', () => {
expect(getArtist(id)).toBe(otherFunction(params));
});
});
Or create special function for generate params and test it separatly. Like prepareArtistParams and use it inside:
const getArtist = (id) => {
const params = prepareArtistParams(id);
return otherFuntion(params);
}
describe('otherFuntion function', () => {
it('should create right params', () => {
expect(prepareArtistParams(id)).toBe(params);
});
});