I have a class Qux
that inherits from class Baa
and I would like to mock Baa
while testing Qux
. That works in principle if I don't try to spy on the mock BaaMock
.
If I would like to spy on the mocked class, the doc says that I should use a jest.fn() instead of the class. However, that does not seem to work correctly: some of the methods of the inheriting class Qux
are lost.
Some example code (also available at https://github.com/stefaneidelloth/testDemoES6Jest) :
Super class Baa (/src/baa.js):
import Foo from './foo.js';
export default class Baa extends Foo {
constructor(name){
super(name);
}
baaMethod(){
return 'baaMethod';
}
overridableMethod() {
return 'baa';
}
}
Inheriting class Qux (/src/qux.js):
import Baa from './baa.js';
export default class Qux extends Baa {
constructor(name){
super(name);
}
quxMethod(){
return 'quxMethod';
}
overridableMethod() {
return 'qux';
}
}
A. Test for inheriting class Qux without a possibility to spy (/test/qux.test.js):
jest.mock('./../src/baa.js', () => {
return class BaaMock {
constructor(name){
this.name = name;
}
baaMethod(){
return 'baaMockedMethod';
}
}
});
import Qux from './../src/qux.js';
describe('Qux', function(){
var sut;
beforeEach(function(){
sut = new Qux('qux');
});
it('quxMethod', function(){
expect(sut.quxMethod()).toEqual('quxMethod');
});
it('baaMethod', function(){
expect(sut.baaMethod()).toEqual('baaMockedMethod');
});
it('overridableMethod', function(){
expect(sut.overridableMethod()).toEqual('qux');
});
});
B. In order to be able to spy on the mocked class, I tried to replace the class with a mock function (also see https://jestjs.io/docs/en/es6-class-mocks):
import Baa from './../src/baa.js';
jest.mock('./../src/baa.js',
function(){
return jest.fn().mockImplementation(
function(name){
return {
name:name,
baaMethod: () =>{ return 'baaMockedMethod';}
};
}
);
}
);
import Qux from './../src/qux.js';
describe('Qux', function(){
var sut;
beforeEach(function(){
//Baa.mockClear();
sut = new Qux('qux');
//expect(Baa).toHaveBeenCalledTimes(1);
});
it('quxMethod', function(){
expect(sut.quxMethod()).toEqual('quxMethod');
});
it('baaMethod', function(){
expect(sut.baaMethod()).toEqual('baaMockedMethod');
});
it('overridableMethod', function(){
expect(sut.overridableMethod()).toEqual('qux');
});
});
As a result, the test fails with following errors:
FAIL test/qux.test.js
Qux
× quxMethod (7ms)
√ baaMethod (4ms)
× overridableMethod (2ms)
● Qux › quxMethod
TypeError: sut.quxMethod is not a function
28 |
29 | it('quxMethod', function(){
> 30 | expect(sut.quxMethod()).toEqual('quxMethod');
| ^
31 | });
32 |
33 | it('baaMethod', function(){
at Object.quxMethod (test/qux.test.js:30:14)
● Qux › overridableMethod
TypeError: sut.overridableMethod is not a function
36 |
37 | it('overridableMethod', function(){
> 38 | expect(sut.overridableMethod()).toEqual('qux');
| ^
39 | });
40 |
41 | });
at Object.overridableMethod (test/qux.test.js:38:14)
I would expect my instance sut
of Qux
to still contain the methods quxMethod
and overridableMethod
that are defined by the class Qux.
=> Is this a bug of jest?
=> If not, why should do I need to implement all methods of Qux in the mock for Baa !!???
=> How do I need to adapt my example code B do successfully mock the class Baa, so that Qux is still able to inherit from it?