Reputation: 1895
I have a service class
Service.js
class Service {
}
export default new Service();
And I am trying to provide a mock implementation for this. If I use something like this:
jest.mock('./Service', () => { ... my mock stuff });
It works fine, however I'm not able to access any variables declared outside of the mock, which is a bit limiting as I'd like to reconfigure what the mock returns, etc.
I tried this (inspired by this other StackOverflow article: Service mocked with Jest causes "The module factory of jest.mock() is not allowed to reference any out-of-scope variables" error)
import service from './Service';
jest.mock('./Service', () => jest.fn);
service.mockImplementation(() => {
return { ... mock stuff }
);
Unfortunately when I am trying to run this, I get the below error:
TypeError: _Service2.default.mockImplementation is not a function
Upvotes: 64
Views: 137342
Reputation: 377
The mock is equal to jest.fn. You need to call jest.fn to create a mocked function.
So this:
jest.mock('./Service', () => jest.fn);
Should be:
jest.mock('./Service', () => jest.fn());
Upvotes: 19
Reputation: 149
ran into similar issues and resolved it by using .mockImplementationOnce
jest.mock('./Service', () => jest.fn()
.mockImplementationOnce(() => {
return { ... mock stuff }
})
.mockImplementationOnce(() => {
return { ... mock other stuff }
})
);
now when you run another test it will return the second mock object.
Upvotes: 13
Reputation: 6496
My file had no default export but instead various other exports, one of which I needed to mock. This ended up working for me:
// services.test.js
const services = require('./services');
...
const innerFunction = jest.fn(() => console.log("calling innerFunction"));
services.functionToMock = jest.fn(() => ({innerFunction}))
I was then later able to test my innerFunction
was properly called by doing
...
expect(innerFunction).toHaveBeenCalledTimes(1);
Upvotes: 0
Reputation: 7
Remove async from your test and DO NOT await expect!
WRONG
it.only('throws error on private visibility', async () => {
await expect(getSteamData(mockSteamId)).rejects.toThrow(ErrorMessage.PRIVATE_VISIBILITY);
});
RIGHT
it.only('throws error on private visibility', () => {
expect(getSteamData(mockSteamId)).rejects.toThrow(ErrorMessage.PRIVATE_VISIBILITY);
});
Upvotes: -2
Reputation: 11
In my case mockImplementation didn't work because I copy paste tests and forgot to remove "async" keyword in this place it('test description', **async** () => {...}
Upvotes: 0
Reputation: 18260
My mistake was that I was resetting the mock before each test. If you do that, be sure to reconfigure the mock implementation.
For example, change this:
let value;
let onPropertyChange: OnPropertyChangeCallback = jest.fn((changes: any) => {
value = changes["testValue"];
});
const user = userEvent.setup();
beforeEach(() => {
jest.resetAllMocks();
});
to this:
let value;
let onPropertyChange: OnPropertyChangeCallback;
const user = userEvent.setup();
beforeEach(() => {
jest.resetAllMocks();
onPropertyChange = jest.fn((changes: any) => {
value = changes["testValue"];
});
});
Upvotes: 1
Reputation: 719
I had same problem as @Janos, the other answers didn't help either. You could do two things :
If you need to mock only a function from Service, in your test file:
import service from './Service';
jest.mock('./Service', () => jest.fn());
service.yourFunction = jest.fn(() => { /*your mock*/ })
If you need to mock the entire Module:
Say your service.js is in javascript/utils, create a javascript/utils/_mocks_ and inside it create a service.js file, you can then mock the entire class in this file, eg:
const myObj = {foo: "bar"}
const myFunction1 = jest.fn(() => { return Promise.resolve(myObj) })
const myFunction2 = ...
module.exports = {
myFunction1,
myFunction2
}
then in your test file you just add:
jest.mock('./javascript/utils/service')
...functions exported from the mockfile will be then hit through your test file execution.
Upvotes: 53
Reputation: 1155
I had similar problem, and the cause was that ".spec.js" file had an
import jest from "jest-mock";
After removing this line, it worked.
Upvotes: 0
Reputation: 1725
You need to store your mocked component in a variable with a name prefixed by "mock" and make sure you return an object with a default property as you import your Service from the default in your "main.js" file.
// Service.js
class Service {
}
export default new Service();
// main.test.js (main.js contains "import Service from './Service';")
const mockService = () => jest.fn();
jest.mock('./Service', () => {
return {
default: mockService
}
});
Upvotes: 5