【问题标题】:Javascript unit testing Promise.all synchronouslyJavascript 单元测试 Promise.all 同步
【发布时间】:2016-11-24 01:43:41
【问题描述】:

我有一个 node.js 应用程序,其中有一个维护状态的对象和一个每 30 秒更新一次状态的更新循环。基本上,它是一个构建监视器,在向前端提供每个管道的最新状态时查询构建机器。

在更新循环中,我需要进行多次调用,为此我需要所有数据才能从中获得任何有用的信息。目前我将所有这些调用包装在一个 Promise 中并使用 Promise.all 等待它们全部完成。

在测试中,我使用 sinon-stub-promise 包同步解析每个 Promise。这对于单个承诺非常有效。然而问题是它不适用于 Promise.all - 至少是同步的。如果我在测试中设置了一个小超时,那么它就可以通过了。

这里有一些sn-ps:

var pipelineRequests = pipelineNames.map(function(pipelineName) {
    return gocdClient.getPipelineStatus(pipelineName);
});

Promise.all(pipelineRequests)
    .then(function(values) {
        values.forEach(function(value) {
            // Do something now all data is available
        });
    });

所以在这里我得到一个pipelinesNames 的列表,然后创建一个请求,该请求为每个管道返回一个承诺。这在我手动测试时有效。

现在是测试代码:

it("should wait for all to return before processing", function() {
        allPipelinesStub
            .returnsPromise().resolves({"NFT-Suite": ["Hour", "Overnight", "Weekend"]});

        pipelineStatusStub
            .withArgs("Hour")
            .returnsPromise().resolves({"status": "Passed", "build-number": 1, "upstream": ["GIT"]});

        pipelineStatusStub
            .withArgs("Overnight")
            .returnsPromise().resolves({"status": "Passed", "build-number": 1, "upstream": ["GIT"]});

        pipelineStatusStub
            .withArgs("Weekend")
            .returnsPromise().resolves({"status": "Passed", "build-number": 1, "upstream": ["GIT"]});

        var pipelinesService = require('../../src/services/pipelinesService');

        var pipelines = pipelinesService.getPipelines();
        should.exist(pipelines);
        pipelines.should.deep.equal({
            "NFT-Suite": {
                "Hour": {
                    "status": "Passed",
                    "build-number": 1,
                    "order": 0
                },
                "Overnight": {
                    "status": "Passed",
                    "build-number": 1,
                    "order": 0
                },
                "Weekend": {
                    "status": "Passed",
                    "build-number": 1,
                    "order": 0
                }
            }
        });
    });

问题是pipelines{}。如果在稍有延迟后拨打pipelinesService.getPipelines(); 就可以了。

单独测试这些很好,因为存根同步解析,我只是找不到强制 Promise.all 在它们全部完成后解析的方法。

有没有办法强制这样做?或者我也可以使用 sinon(或其他东西)来消除它吗?

感谢任何帮助

【问题讨论】:

  • 你必须在上面的 sn-p 中返回 Promise.all 的结果。在下面的测试中,返回 Promise 并链接一个 then 块,您将在其中返回从 Promise 返回的值。
  • 不,没有办法做到这一点。 Promise 是异步的。要测试涉及它们的任何内容,请编写异步测试。
  • 我不确定我是否遇到了您的问题,您是否遇到了测试本身的问题?如果是这样,有一个参数叫做 done,所以你可以得到它并在 promise.all 回调中调用它,看:semaphoreci.com/community/tutorials/… at "Async Tests with sinon.test"
  • 我试图避免在任意超时的情况下进行异步操作,因为似乎应该有更好的方法。我宁愿不返回 promise.all,因为它不是该方法的真正用途,它用于根据返回请求的值更新状态。
  • 要运行异步测试,您需要知道异步任务何时完成。如果没有返回 promise 或没有调用 'done' 回调,mocha 会在几秒后自动触发超时。

标签: javascript node.js unit-testing promise sinon


【解决方案1】:

您需要决定要测试的内容。如果您想使用Promise.all 测试代码,您需要返回承诺 - 或至少 some 承诺表明操作已完成。这并不意味着您必须从现有代码中返回承诺:您可以将逻辑包装在另一个私有函数“_foo”中并让现有代码使用它,然后测试“foo " 从外部而不是您的原始代码。

如果这是在 getPipelines() 内,那么只要你这样做,测试就可以正常工作:

return pipelinesService.getPipelines().then(() => {
    should.exist(pipelines);
    pipelines.should.deep.equal({ 
    // more code ....
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 1970-01-01
    • 2018-01-02
    • 2012-07-15
    相关资源
    最近更新 更多