如何存根从另一个函数调用的模块函数

How to stub a module function that is called from another function

我的 module.ts 文件有两个函数:

export async function foo() {
    var barVal = await bar();
    doSomethingWithBarVal(barVal);
}

export async function bar(): Bar {
    return await somethingAsync();
}

在我的测试中,我想 stub bar() 和 return a mock for Bar(returned 值 bar())

我目前的测试是这样的:

var module = require('module.ts');
var myStub = sinon.stub(module, 'bar').resolves(myMock);
await foo();
expect(myStub.calledOnce);

然而,expect 总是失败并调用 'real' bar()
如果我直接从我的测试调用 bar(),那么存根 被调用 但我想测试整个流程。

你的方法的问题是你正在存根模块对象(exports 因为你在测试中使用的是 commonjs require)而你的 foo 函数使用 bar 在模块范围内可用。

要解决此问题,您可以在此处进行一些选择。

1。又快又脏

foo

中使用exports.bar代替bar
export async function foo() {
    var barVal = await exports.bar();
    doSomethingWithBarVal(barVal);
}

这种方法实际上是一种 hack,它利用了您的模块将被转换为 commonjs 格式这一事实。这可能有一天不是真的,但现在有点用。

2。拥抱 ES 模块的静态特性

接受 ES 模块是静态的这一事实。通过明确允许指定 bar 作为其参数

来使您的函数 "testable again"
export async function foo(_bar = bar) {
    var barVal = await _bar();
    doSomethingWithBarVal(barVal);
}

// test.js
await foo(mockBarImplementation)

3。高级

使用一些 IoC/DI 实现。例如 typescript-ioc