简体   繁体   English

Javascript单元同步测试Promise.all

[英]Javascript unit testing Promise.all synchronously

I have a node.js application in which I have an object that maintains state and an update loop that updates this state every 30 seconds. 我有一个node.js应用程序,其中我有一个维护状态的对象和一个每30秒更新一次这种状态的更新循环。 Basically it is a build monitor that queries a build machine while serving the latest state of each pipeline to the frontend. 基本上它是一个构建监视器,它在向前端提供每个管道的最新状态时查询构建机器。

In the update loop I need to make several calls, for which I need all the data to make anything useful from it. 在更新循环中,我需要进行多次调用,为此我需要所有数据来从中进行任何有用的操作。 Currently I wrap all these call in a Promise and use Promise.all to wait for them all to finish. 目前我将所有这些调用包装在Promise中并使用Promise.all等待它们全部完成。

In the test I resolve each promise synchronously with the sinon-stub-promise package. 在测试中,我与sinon-stub-promise包同步解析每个promise。 This works perfectly for single promises. 这适用于单一承诺。 The problem however is that it does not work for Promise.all - at least synchronously. 然而问题是它对Promise.all不起作用 - 至少是同步的。 If I put a small timeout in my test then it passes fine. 如果我在我的测试中放了一个小超时,那么它通过正常。

Here are some snippets: 以下是一些片段:

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
        });
    });

So here I get a list of pipelinesNames and then create a request which returns a promise for each one of these pipelines. 所以这里我得到一个pipelinesNames列表,然后创建一个请求,为每个管道返回一个promise。 This works when I manually test it. 这在我手动测试时有效。

Now for the test code: 现在为测试代码:

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
                }
            }
        });
    });

The problem is pipelines is {} . 问题是pipelines{} If a call pipelinesService.getPipelines(); 如果调用pipelinesService.getPipelines(); after a slight delay it works fine. 经过一段时间的延迟,它工作正常。

Testing these individually is fine because the stub resolves synchronously, I just can't find a way to force Promise.all to resolve after they all complete. 单独测试这些是很好的,因为存根同步解决,我只是找不到强制Promise.all完成后解决的方法。

Is there a way to force this ? 有没有办法强迫这个? Or can I use sinon (or something else) to stub that out too ? 或者我可以使用sinon(或其他东西)将其存在?

Appreciate any help 感谢任何帮助

You need to decide what you are testing. 你需要决定你在测试什么。 If you want to test the code using Promise.all you need to return the promise - or at least some promise to indicate that the operation has completed. 如果你想使用Promise.all测试代码,你需要返回promise - 或者至少是一些承诺,表明操作已经完成。 It doesn't mean you have to return the promise from your existing code: you can wrap the logic in another, private, function "_foo" and let your existing code use that, and then test "foo" from the outside instead of your original code. 这并不意味着您必须从现有代码返回承诺:您可以将逻辑包装在另一个私有函数“_foo”中,让现有代码使用它,然后从外部测试“foo”而不是原始代码。

If this is inside getPipelines() the test would simply work if you just did: 如果这是在getPipelines()内部, getPipelines()如果你刚刚做了测试,测试就会起作用:

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

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

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