首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用should.js断言函数已‘等待’异步函数

如何使用should.js断言函数已‘等待’异步函数
EN

Stack Overflow用户
提问于 2018-11-29 07:04:26
回答 2查看 1K关注 0票数 4

我有一个调用另一个异步函数g的异步函数f。为了测试f是否调用了g,我使用sinon截断了g,并断言它是使用should.js调用的。

代码语言:javascript
复制
'use strict';

require('should-sinon');
const sinon = require('sinon');

class X {
    async f(n) {
        await this.g(n);
        // this.g(n); // I forget to insert `await`!
    }
    async g(n) {
        // Do something asynchronously
    }
}

describe('f', () => {
    it('should call g', async () => {
        const x = new X();
        sinon.stub(x, 'g').resolves();
        await x.f(10);
        x.g.should.be.calledWith(10);
    });
});

但是,即使我在f中调用g时忘记使用await,这个测试也会通过。

捕获此错误的方法之一是让存根返回一个虚拟的promise,并检查是否调用了它的then

代码语言:javascript
复制
it('should call g', async () => {
    const x = new X();
    const dummyPromise = {
        then: sinon.stub().yields()
    };
    sinon.stub(x, 'g').returns(dummyPromise);
    await x.f(10);
    x.g.should.be.calledWith(10);
    dummyPromise.then.should.be.called();
});

但这有点麻烦。有什么方便的方法可以做到这一点吗?

EN

回答 2

Stack Overflow用户

发布于 2018-11-29 07:52:19

您的f示例显示了有缺陷的代码设计,如果您在没有async/await语法的情况下编写相同的函数,则会变得更加明显:

f(n) { return g(n).then(()=>{}); }

这实现了同样的行为-- g的解析是否变得难以判断(假设你不知道f是否返回了g的promise,这就相当于不知道f是否等待了g)。如果fg的结果不感兴趣,它应该只返回它,而不是隐藏它。然后你就可以简单地测试结果了。

如果您的观点是,f可能必须依次触发几个async调用await几个g_1g_2,...要解决这个问题,您可以通过在g_n+1的存根中断言g_n的虚拟承诺已经解决来构建测试链。一般来说,测试虚拟承诺的状态的方法是很好的。

票数 0
EN

Stack Overflow用户

发布于 2018-12-04 00:03:25

与其截断then,不如截断g,使其在下一次事件循环迭代中设置一些布尔值。然后,您可以在调用f之后检查此布尔值,以确保f等待它:

代码语言:javascript
复制
it('should call g', async () => {
    const x = new X();
    let gFinished = false;
    sinon.stub(x, 'g').callsFake(() => {
        return new Promise((resolve) => {
            setImmediate(() => {
                gFinished = true;
                resolve();
            });
        });
    });
    await x.f(10);
    x.g.should.be.calledWith(10);
    gFinished.should.be.true();
});

编辑:当然,这不是一个完美的保证,因为你可以让f等待任何承诺,至少等待g解析的时间一样长。如下所示:

代码语言:javascript
复制
async f(n) {
    this.g(n);
    await new Promise((resolve) => {
        setImmediate(() => {
            resolve();
        });
    });
}

这将导致我编写的测试通过,即使它仍然是不正确的。因此,这实际上取决于您对测试的严格程度。您是否希望从字面上看不可能出现假阳性?或者,如果一些明显的骗局可能会把它抛到脑后,这是可以的吗?

在大多数情况下,我发现后者是可以的,但实际上这取决于您和/或您的团队。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53529435

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档