I have a question about how can I mock an ES6 class instance using Jest which is used by the method I actually want to test. My real case is trying to test a Redux async action creator that make a request and dispatch some action depending on the request result.
This is a simplified example of the use case :
// communication.js
// An exported ES6 class module with proxy to the request library.
import post from './post';
export default class communication {
getData(data, success, error) {
const res = post(data);
if(res) {
success();
} else {
error();
}
}
}
// communicatorAssist.js
// A redux async function using communication.js
import communication from './communication';
// ...
export function retrieveData() {
return dispatch => {
const data = { name: 'michel'};
communication.getData(data,
(res) => dispatch(successAction(res)),
(res) => dispatch(errorAction(res));
}
}
// communicatorAssist.test.js testing the communicatorAssist
import { retrieveData } from 'communicatorAssist';
// communication.getData should call success callback
// for this test.
it('Should call the success callback', () => {
retrieveData();
// Assert that mocked redux store contains actions
});
// communication.getData should call error callback
// for this test.
it('Should call the error callback', () => {
retrieveData();
// Assert that mocked redux store contains actions
});
What I want is mocking the communication class in the test and change the behaviour of the getData()
function in each test to call success
and error
callbacks without any call to post method.
I only success to mock the getData()
function for the whole test file with this snippet at the top of it :
import communication from '../communication'
jest.mock('../communication', () => (() => ({
getData: (success, error) => success()
})));
but I can't switch between implementation in different test case.
I figure that something using .mockImplementation()
could do the stuff but I can't make this work in my case (I saw examples using it for module exporting functions but not for classes ).
Does anyone have an idea ?
Edit :
I forgot a part in the code exemple : the communication class instance creation which I think is the "problem" for mocking it :
const com = new communication();
If com
is instanciated at a global level in the communicatorAssist.js file : it fail with communication.getData is not a function error.
But if I set the instanciation inside the retrieveData()
function, Andreas Köberle snippet work's fine :
import communication from '../communication'
jest.mock('../communication', () => jest.fn());
communication.mockImplementation(
() => ({
getData: (success, error) => success()
})
)
(jest.mock()
factory parameter need to return a function not directly jest.fn
)
I don't know why it's not working using a file global scope instance.
To spy on an exported function in jest, you need to import all named exports and provide that object to the jest. spyOn function. That would look like this: import * as moduleApi from '@module/api'; // Somewhere in your test case or test suite jest.
To test method implementation using spies with Jest we use the jest. spyOn() function. jest. spyOn() is called with two required parameters - the object and the object method identifier we're spying on.
To mock a function's return value in Jest, you first need to import all named exports from a module, then use mockReturnValue on the imported function. You can use the * as <alias> inside an import statement to import all named exports. Then, you need to chain mockReturnValue off of jest.
You need to mock the module with jest.fn()
then you can import it and change the behaviour of it using mockImplementation
:
import communication from '../communication'
jest.mock('../communication', jest.fn());
communication.mockImplementation(
() => ({
getData: (success, error) => success()
})
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With