我想在Jest单元测试中扩充但不完全替换模拟构造函数的实例。
我想为实例添加一些值,但要保持Jest的自动模拟优势。
例如:
A.js
module.exports = class A {
constructor(value) {
this.value = value;
}
getValue() {
return this.value;
}
}
获得一些自动模拟真棒:
jest.mock('./A');
使用automock,实例有一个模拟.getValue()
方法,但它们没有.value
属性。
记录在案的way of mocking constructors是:
// SomeClass.js
module.exports = class SomeClass {
m(a, b) {}
}
// OtherModule.test.js
jest.mock('./SomeClass'); // this happens automatically with automocking
const SomeClass = require('./SomeClass')
const mMock = jest.fn()
SomeClass.mockImplementation(() => {
return {
m: mMock
}
})
const some = new SomeClass()
some.m('a', 'b')
console.log('Calls to m: ', mMock.mock.calls)
将此方法用于A
:
jest.mock('./A');
const A = require('./A');
A.mockImplementation((value) => {
return { value };
});
it('does stuff', () => {
const a = new A();
console.log(a); // -> A { value: 'value; }
});
关于这一点的好处是,您可以对返回的值执行任何操作,例如初始化.value
。
缺点是:
.getValue()
自己添加到实例jest.fn()
模拟函数,例如:如果我创建两个A
实例,则每个实例都需要jest.fn()
方法的.getValue()
模拟函数SomeClass.mock.instances
未填充返回值(GitHub ticket)有一件事没有用(我希望也许Jest做了一些魔术):
A.mockImplementation((value) => {
const rv = Object.create(A.prototype); // <- these are mocked methods
rv.value = value;
return rv;
});
不幸的是,所有实例都使用相同的方法(正如人们所期望的那样,但值得一试)。
我的下一步是通过检查原型来生成模拟(我猜),但我想看看是否有既定的方法。
提前致谢。
答案 0 :(得分:1)
以下对我有用:
A.mockImplementation(value => {
const rv = {value: value};
Object.setPrototypeOf(rv, A.prototype);
return rv
})
答案 1 :(得分:0)
事实证明,这是固定的(从24.1.0开始),问题中的代码按预期工作。
回顾一下,给定类A
:
A.js
module.exports = class A {
constructor(value) {
this.value = value;
}
setValue(value) {
this.value = value;
}
}
该测试现在将通过:
A.test.js
jest.mock('./A');
const A = require('./A');
A.mockImplementation((value) => {
const rv = Object.create(A.prototype); // <- these are mocked methods
rv.value = value;
return rv;
});
it('does stuff', () => {
const a = new A('some-value');
expect(A.mock.instances.length).toBe(1);
expect(a instanceof A).toBe(true);
expect(a).toEqual({ value: 'some-value' });
a.setValue('another-value');
expect(a.setValue.mock.calls.length).toBe(1);
expect(a.setValue.mock.calls[0]).toEqual(['another-value']);
});