【问题标题】:Asynchronous Javascript with Promises and unit/integration tests带有 Promises 和单元/集成测试的异步 Javascript
【发布时间】:2017-06-02 05:16:28
【问题描述】:

我在 Javascript 和异步领域还很陌生,似乎两者都让我头疼。

所以,我有一个第 3 方客户端 API,它具有以下 async 方法 getItem(id)

现在我正在尝试根据其子项确定父项的状态:

getStatus = function(ids) {
    var failedCount = 0;
    var successCount = 0;
    var warningCount = 0;

    ids.forEach(function(id) {
        //calling the async function
        getItem(id).then(function(item) {
            var state = item.State;
            if(state == "Success") {
                successCount++;
            } else if(state == "Failed") {
                failedCount++;
            } else if(state == "Warning") {
                warningCount++;
            }
        });
    });
    if(failedCounter > 0) {
        return "Failed";
    } else if(warningCounter > 0) {
        return "Warning";
    } else if(successCounter == ids.length) {
        return "Success";
    } else {
        return "Not run yet";
    }
}

然后,为了确保我不会在途中破坏任何东西,我决定进行一些集成测试,所以我选择了QUnitqunit-parameterize

QUnit.cases([
    {
        title : "Success, Failed => Failed",
        ids : [1,2],
        expectedItemStateAfter : "Failed"
    }
    ]).test( "", function( params, assert ) {
          var done = assert.async(2);
          setTimeout(function() {
             var value = getStatus(params.ids);       
             assert.equal(value, params.expectedItemStateAfter);
             done();
            }, 2000);
});

尝试调整setTimeout 超时,尝试使用assert.async(2)assert.async();,根据他们的文档,每个QUnit 的默认值,但无济于事,最终结果每次甚至在一堆读数之后仍然相同并试图理解我不知道我做错了什么:

1. failed     @ 2004 ms
Expected: "Failed"
Result:   undefined
Diff:   "Failed" undefined 

【问题讨论】:

  • getItem(id) 调用需要串行还是并行进行
  • @JaromandaX 没有一个 Promise 使用来自其他 Promise 的结果,所以我会说并行。
  • 从发布的代码中,这似乎是一个合理的假设 - 但人们不知道未命名的第 3 方 API 的内部结构:p
  • 请注意,在代码块格式中使用 async 这个词可能会使一些 Javascript 开发人员感到困惑。 Promise 是在 JS 中进行异步的一种方式,但 async/await 是另一回事。见async functions

标签: javascript unit-testing asynchronous


【解决方案1】:

您的 getStatus 函数在任何异步调用解析之前返回结果。您需要让getStatus 返回一个当所有其他承诺使用Promise.all 解决时解决的承诺:

var getStatus = function(ids) {
    var failedCount = 0;
    var successCount = 0;
    var warningCount = 0;

    return Promise.all(ids.map(function(id) {
        return getItem(id).then(function(item) {
            var state = item.State;
            if (state === "Success") {
                successCount++;
            } else if (state === "Failed") {
                failedCount++;
            } else if (state === "Warning") {
                warningCount++;
            }
        });
    })).then(function() {
        if (failedCounter > 0) {
            return "Failed";
        } else if (warningCounter > 0) {
            return "Warning";
        } else if (successCounter === ids.length) {
            return "Success";
        } else {
            return "Not run yet";
        }
    });
};

然后您需要调整测试代码,使其使用 Promise 而不是 setTimeout。请注意,您可以从 QUnit.test 回调中返回一个 thenable 对象,它会自动处理 Promise 的解析。

QUnit.cases([
    { title: "Success, Failed => Failed", ids: [1, 2], expectedStatus: "Failed" }
]).test("getStatus() test", function(params, assert) {
    return getStatus(params.ids).then(function(value) {
        assert.equal(value, params.expectedStatus);
    });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 2020-10-26
    • 1970-01-01
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多