简体   繁体   English

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

[英]How to stub a module function that is called from another function

My module.ts file has 2 functions:我的module.ts文件有两个功能:

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

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

In my tests I want to stub bar() and return a mock for Bar (the returned value of bar() )在我的测试中,我想stub bar() 并返回Barmockbar()的返回值)

My current test looks like this:我目前的测试是这样的:

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

However, the expect always fails and the 'real' bar() is called.但是, expect总是失败,并且调用了“真正的” bar()
If I call bar() directly from my test, then the stub is called but I want to test the whole flow.如果我直接从我的测试中调用bar() ,则会调用存根但我想测试整个流程。

The problem with your approach is that you are stubbing module object ( exports since you are using commonjs require in your test) while your foo function uses bar available in module scope.您的方法的问题在于您正在存根模块对象( exports因为您在测试中使用的是 commonjs require ),而您的foo函数使用模块范围内的bar可用。

To fix this you have a few options here.要解决此问题,您有几个选择。

1. Quick and dirty 1.又快又脏

Use exports.bar instead of bar in foofoo使用exports.bar而不是bar

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

This approach is actually a hack that uses the fact that your module will be transpiled to commonjs format.这种方法实际上是一种 hack,它利用了您的模块将被转换为 commonjs 格式这一事实。 Which might be not true someday but kinda works for now.这可能有一天不是真的,但现在有点工作。

2. Embrace static nature of ES modules 2. 拥抱 ES 模块的静态特性

Embrace the fact that ES modules are static.接受 ES 模块是静态的这一事实。 Make your function "testable again" by explicitly allowing to specify bar as its argument通过明确允许将bar指定为其参数,使您的函数“再次可测试”

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

// test.js
await foo(mockBarImplementation)

3. Advanced 3.进阶

Use some IoC/DI implementation.使用一些IoC/DI实现。 For example typescript-ioc例如打字稿-ioc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM