如何通过 SinonJs 模拟库?

How to mock library by SinonJs?

我有一个文件:浏览器-launcher.ts

import * as Browser from "@lib/browser";
    
class BrowserLauncher {
    launch(options) {
       browser = Browser(options);
    }
}
    
export const browserLauncher = new BrowserLauncher()

如何模拟库“@lib/browser”来测试 BrowserLauncher 的启动方法?

如何在模块browser-launcher.ts中正确测试变量browserLauncher?

Sinon 并不是一个真正处理您的特定问题的库,它是在模块加载器级别用一个模块替换一个假模块,因为它非常特定于您工作的环境。 Sinon 只处理替代品的实际创建(模拟或存根实现)。这样的模块 substitution 是由特定的第三方库解决的,比如 proxyquire, rewire 之类的,你要替换的依赖模块在测试文献中被称为“link seam” .

您可以在 Sinon 团队中查看我们关于如何在 CommonJS 环境中执行此操作的操作方法:https://sinonjs.org/how-to/link-seams-commonjs/

看到 @lib/... 字符串让我认为这是一个特定于 webpack 的问题,在这种情况下,您应该找到一些处理 webpack 的模块替换库。 inject-loader.

就是这样的一个库

话虽如此,有时 Sinon 可用于替换某些模块上的导出 ,但这完全是特定于环境的!符合规范的 ES 模块导出一个不可变的命名空间,因此您 不应该 能够覆盖导出。

您可以在我们的 test code 中看到 Sinon 的预期行为,您可以在其中看到诸如 export default { foo(){} } 之类的导出可以存根(因为它的成员不是不可变的),而 export function foo(){}不能打桩。

您可以存根导出的唯一方法是让您的 ES 环境不兼容:生成 可写的导出 或禁用只读性质。

在不使用 link 接缝的情况下测试模块

我详细介绍了两种无需外部工具即可使用普通依赖注入来执行此操作的方法。你应该检查一下,因为它非常简单,但缺点是它需要对你的生产代码进行一个小的仅测试更改来促进它。这是利弊的平衡:更改代码或引入更多依赖项。

我写了 a more elaborate example of this technique on the Sinon issue 跟踪器,你可能想看看,我在其中展示了如何可选地 注入依赖项。