我们在使用Jest进行单元测试时遇到了一个令人不安的错误。
问题: Jest 无法访问内部对象方法
案例:有一个lol
对象,其中包含b()
方法,如果我们直接调用b方法, Jest 就会失败,如果我们用lol.b()
调用它
有人已经遇到过这个问题吗?有更好的解决方法吗?
代码:
describe('Jest bug', () => {
it('Jest fail', () => {
const lol = (() => {
const a = () => {
console.log("console a");
b();
};
const b = () => {
console.log("console b");
};
return {
a,
b
};
})();
const spy = jest.spyOn(lol, 'b');
lol.a();
expect(spy).toHaveBeenCalled()
});
it('Jest success', () => {
const lol = (() => {
const a = () => {
console.log("console OK a");
lol.b();
};
const b = () => {
console.log("console OK b");
};
return {
a,
b
};
})();
const spy = jest.spyOn(lol, 'b');
lol.a();
expect(spy).toHaveBeenCalled()
});
});
答案 0 :(得分:2)
Jest spyOn
在内部替换具有间谍功能的对象方法 - 间谍功能是附加的'对象,它不会将原始函数包装到哪个对象属性指向。如果你在lol.b
方法上设置间谍,Jest会做这样的事情(当然下面的代码是大量的简化,只是为了显示一般的想法):
let b = function() {
...
};
let lol = {
b: b
};
spyOn(lol, 'b');
//Jest internally does something like this
lol.b = function jestSpyFunction() {
...
};
因此,如果你现在直接调用b()
,那么间谍完全没有意识到这一点,因为在这种情况下不会调用jestSpyFunction
- 只有在你使用lol.b()
时才会调用它。登记/>
因此,在我看来,lol
的第二个实现是正确的,应该这样做以使代码可测试。此外,您将a
和b
功能定义为“私人”和“私人”功能。 (在匿名函数内)所以它是正确的和预期的行为,他们无法从外部范围访问(即使是间谍间谍)。