考虑一下我们有一些方法的类。我们想窥探是否调用方法B,而一旦执行方法A,则将结果返回给调用方,而方法B将异步执行。该类如下所示。
class Parent {
constructor() {
this.conf = [{ id:'1', func: Parent.methodA.bind(Parent)}, { id:'2', func: Parent.methodB.bind(Parent)}]
}
static methodA() {
console.log('methodA is called from methodC');
return 'methodA';
}
static methodB() {
console.log('methodB is called from methodC');
return 'methodB';
}
methodC(conf) {
conf.forEach((eachConf) => {
if(eachConf.id === '1') {
setImmediate(() => {
// Just to call method with conf = [{ id:'2', func: this.methodB.bind(this)}]
this.methodC(conf.slice(1));
})
return eachConf.func();
}
return eachConf.func();
});
}
}
module.exports = Parent;
在笑话测试文件中,调用methodC并希望确保methodA具有返回值,并且希望确保methodB也被调用。 testSpy.js const Parent = require('./ parent');
it('check methodA and methodB called', async () => {
const methodA = jest.spyOn(Parent, 'methodA');
const methodB = jest.spyOn(Parent, 'methodB');
const instance = new Parent();
instance.methodC(instance.conf);
expect(methodA).toHaveBeenCalled();
//How to spyOn methodB.
//expect(methodB).toHaveBeenCalled();
});
返回结果后可以运行几种方法。希望确保所有步骤均已执行,并且最好也获得每个步骤的结果。
答案 0 :(得分:0)
使用setImmediate
时,您需要使用jest.useFakeTimers()
和jest.runAllTimers()
来立即调用您放入setImmediate
中的每个回调。
it('check methodA and methodB called', async () => {
jest.useFakeTimers()
const methodA = jest.spyOn(Parent, 'methodA');
const methodB = jest.spyOn(Parent, 'methodB');
Parent.methodC(Parent.conf);
jest.runAllTimers()
expect(methodA).toHaveBeenCalled();
//How to spyOn methodB.
//expect(methodB).toHaveBeenCalled();
});
答案 1 :(得分:0)
.bind
creates a new function,因此func
被设置为this.methodA.bind(this)
创建的新功能。
运行jest.spyOn(Parent, 'methodA');
时,它会用间谍代替methodA
,但这对func
没有任何影响。
调用func
时会调用新函数,而不会调用methodA
上的间谍。
如果要使用spy
来验证是否调用了methodA
,必须确保调用了methodA
。
在这种情况下,您无需使用this
将bind
绑定到this.methodA
(这会创建一个新函数),而是可以从箭头函数中调用this
(因为箭头函数capture the this
of the enclosing lexical scope ...在这种情况下,是构造函数中的constructor() {
this.conf = [
{
id: '1',
func: (...args) => this.methodA(...args)
},
{
id: '2',
func: (...args) => this.methodB(...args)
}
];
}
):
func
然后,当调用methodA
时,它将调用spy
,后者将调用it('check methodA and methodB called', async () => {
jest.useFakeTimers();
const methodA = jest.spyOn(Parent, 'methodA');
const methodB = jest.spyOn(Parent, 'methodB');
const instance = new Parent();
instance.methodC(instance.conf);
jest.runAllTimers();
expect(methodA).toHaveBeenCalledTimes(1); // SUCCESS
expect(methodB).toHaveBeenCalledTimes(2); // SUCCESS
});
并且测试将通过。
更新
这是您更新后的代码示例的有效测试:
jest.useFakeTimers
setImmediate
用模拟记忆来代替jest.runAllTimers
之类的计时器函数,以记住调用它们的内容。然后methodA
运行使用计时器函数安排的所有回调。
methodC
第一次被调用。
methodB
第一次被调用,methodC
被调用,并且由于methodC
回调而再次调用setImmediate
时也被调用。