Reputation: 897
I have an ES6 class which I need to mock it's methods. Following the documentation i made a manual mock of this, and got the constructor to both be called and asserted.
My function that consumes this class is just a basic function that runs one of the class methods.
test.js
const mockConnect = jest.fn();
const mockAccess = jest.fn();
jest.mock('../../src/connection');
const connection = require('../../src/connection').default;
connection.mockImplementation(() => {
return {
connect: mockConnect,
access: mockAccess.mockReturnValue(true),
};
});
caller_function();
expect(connection).toHaveBeenCalled(); // works properly as the constructor is called
expect(connection).toHaveBeenCalledWith('something'); // works
expect(mockAccess).toHaveBeenCalled(); // says it was not called when it should have
caller_function.js
import connection from 'connection';
const conn = new connection('something');
export function caller_function() {
conn.access(); // returns undefined when mock says it should return true
}
Upvotes: 1
Views: 1501
Reputation: 8652
This is happening because you're using mockImplementation()
instead of a manual mock or the factory parameter to jest.mock()
, and your mocked object is being created during the module loading process, since the constructor call is not inside of any function. What's happening is:
jest.mock('../../src/connection')
runs and sets connection
to be an automatic mock.conn
object is created using the automatic mock. Therefore its access
method returns undefined.mockImplementation()
happens, changing the connection
mock. However, since the conn
object has already been created, it doesn't get the custom implementation.Moving the constructor call into caller_function
is one way to fix it:
export function caller_function() {
const conn = new connection('something');
conn.access();
}
You could also use the factory parameter to jest.mock()
, specifying the implementation there, instead of calling mockImplementation()
. That way you won't have to change your implementation code:
const mockConnect = jest.fn();
const mockAccess = jest.fn();
import connection from '../../src/connection';
jest.mock('./so-import', () => {
return jest.fn().mockImplementation(() => {
return {
connect: mockConnect,
access: mockAccess.mockReturnValue(true)
};
});
});
...
BTW the convention for ES6 class names is to begin with an uppercase letter. I was temporarily confused by the lowercase name connection
.
Upvotes: 1
Reputation: 463
Did you try doing connection.mockClear();
before you write a mockImplementation for the methods?
Also please refer to this https://jestjs.io/docs/en/es6-class-mocks
Upvotes: 0