使用ES模块,我们将一些导出的函数定义为const
,这通常是一种标准做法。但是,在单元测试期间,这些const函数不能被删除,这从单元测试的角度来看似乎有问题。例如,
import * as fs from 'fs';
import { bindNodeCallback } from 'rxjs';
import { map } from 'rxjs/operators';
// readFile :: string, string => Observable<string>
export const readFile$ = bindNodeCallback(fs.readFile);
// readJson :: string => Observable<any>
export function readJson(fileName) {
return readFile$(fileName, 'utf-8')
.pipe(map((rawFile) => JSON.parse(rawFile)));
}
现在单元测试readJson,我通常想要存根readFile$
函数。不幸的是,遵循Sinon代码并不起作用:
// Setup data - stubs / mocks
const stub = sinon.stub(myFs, 'readFile$').returns(json$);
由于Sinon只是更改引用myFs.readFile$
,原始const
仍指向原始函数,而该函数又由readJson
函数调用。
任何建议 - 如何在同一个模块中真正存根/模拟常量函数?
答案 0 :(得分:0)
const
是常量,无法使用“普通”代码更改它。不幸的是sinon
并不神奇。您需要检测代码以允许更改常量值。
假设您正在使用babel进行转换,您可以使用babel-plugin-rewire
。
将其添加到您的babel配置后,您可以在测试代码中进行以下注射
import { default as readJson, __RewireAPI__ as rewire } from './path/to/readJson.js'
const stub = sinon.stub(myFs, 'readFile$').returns(json$)
rewire.__set__('readFile$', stub)
// readJson() would now call provided stub
答案 1 :(得分:0)
我相信 Sinon 有办法做到这一点,而无需使用第三方软件包(例如 Babel)。这是他们关于它的文档页面,有一个简单的例子:How to stub a dependency of a module。我只是自己试了一下,似乎有效。
抱歉,我没有时间在回复中分享任何代码。我知道这种形式很糟糕:-/ 但希望该链接可以帮助某些人。