Javascript SpyOn单独导出ES6函数
tl;医生:Javascript SpyOn单独导出ES6函数,javascript,unit-testing,ecmascript-6,jasmine,Javascript,Unit Testing,Ecmascript 6,Jasmine,tl;医生: 我用茉莉花 我想测试aaa函数,该函数从同一位置调用bbb 模块 我想监视bbb,但最终aaa称为 原始的bbb功能,不是间谍 我如何强制aaa呼叫间谍? 模块: export function aaa() { return bbb(); } export function bbb() { return 222; } 测试: import * as util from 'my-module'; describe('aaa test', () => { le
aaa
函数,该函数从同一位置调用bbb
模块李>
bbb
,但最终aaa
称为
原始的bbb
功能,不是间谍李>
我如何强制aaa
呼叫间谍?
模块:
export function aaa() {
return bbb();
}
export function bbb() {
return 222;
}
测试:
import * as util from 'my-module';
describe('aaa test', () => {
let bbbSpy: Spy;
beforeEach(() => {
bbbSpy = spyOn(util, 'bbb');
});
it('should return SPYED', () => {
bbbSpy.and.returnValue('SPYED!!');
const result = util.aaa();
expect(result).toEqual('SPYED!!'); // Doesn't work - still 222
});
});
所以,基本上这是行不通的。有人能帮我吗
p.S.我不想更改模块的代码,因为在这种情况下,我必须更改项目中大量的代码。我需要一个测试的通用解决方案。即使是不同的框架,也有一个相关的问题可以告诉您为什么这不起作用:。基本上,您将无法访问该函数的固定引用,而是要明确该函数与模块上下文中的函数相同 我知道这并不能满足你在问题中提出的限制条件,但它只是表明你想通过使用spy实现的目标是不可能的
使用JavaScript,无法交换对某些内容的引用。不能调出模块内部的函数。在您的示例中,当您尝试使用spyOn.and.returnValue覆盖bbb时,您只是在测试中修改了本地绑定bbb,但它对其他文件中的bbb绑定没有影响。编写代码时没有考虑到测试问题,如果不进行重构,它将无法获得完全覆盖 在这种情况下,不可能强制
aaa
呼叫间谍。直接指模块范围内的bbb
功能。没有可监视的对象
这基本上与JavaScript作用域问题相同:
(() => {
var bar = 1; // there's no way to reach this variable from the outside
})();
如果函数始终被称为对象属性,则可以这样做。ES模块中没有这样的对象,但这种方法在CommonJS模块中很常见,特别是出于可测试性的考虑(像Webpack这样的捆绑工具都支持):
通过这种方式,bbb
属性可以通过spyOn(util,'bbb')
监视*
导入,如原始代码所示。这不适用于具有只读导出且不与CommonJS模块互操作的本机ES模块
如果
aaa
和bbb
驻留在不同的模块中,那么这样做可能更容易。这样就有可能模拟模块(这不适用于本机ES模块)。@Rajesh Nope。我的意思是aaa
按原样调用bbb()
,而不是util.bbb()
。我无法遍历所有代码并更改所有函数以使用这种方式。此外,在这种情况下,模块的函数不会单独导出。@Rajesh实际上不起作用,但感谢答案是正确的,为了测试它,您要么进行重构,要么不在这里使用spy,只测试函数aaa()的输出,也就是说,如果代码是功能性的,那么在这种情况下意味着对bbb()的调用影响返回值,而不仅仅是像登录控制台这样的副作用。
exports.aaa = function aaa() {
return exports.bbb();
}
exports.bbb = function bbb() {
return 222;
}