首页 > 解决方案 > 如何存根从另一个函数调用的模块函数

问题描述

我的module.ts文件有 2 个功能:

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

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

在我的测试中,我想stubbar() 并返回一个mockfor Bar(的返回值bar()

我当前的测试如下所示:

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

但是,expect总是失败并且调用“真实” bar()
如果我bar()直接从我的测试中调用,那么会调用存根,但我想测试整个流程。

标签: javascriptnode.jstypescriptsinon

解决方案


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

要解决此问题,您有几个选择。

1. 又快又脏

使用exports.bar而不是barfoo

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

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

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

接受 ES 模块是静态的这一事实。bar通过明确允许将其指定为参数,使您的函数“再次可测试”

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

// test.js
await foo(mockBarImplementation)

3.高级

使用一些IoC/DI实现。例如打字稿-ioc


推荐阅读