简体   繁体   中英

Asynchronous Javascript with Promises and unit/integration tests

I'm quite new in the world of Javascript and asynchronous and it seems that both are giving me headaches.

So, I have a 3rd party client API that has the following async method getItem(id)

Now I'm trying to determine the status for a parent item based on it's children:

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

Then, to make sure that I won't break anything on the way, I decided to go with some integration tests, so I settled for QUnit and qunit-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);
});

Tried to tweak the setTimeout timeout, tried with assert.async(2) and assert.async(); , the default value per QUnit per their documentation, but no avail, the end result is still the same everytime and even after a bunch of readings and trying to understand I have no idea what I'm doing wrong:

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

Your getStatus function is returning a result before any of the async calls resolve. You need to make getStatus return a promise that resolves when all of the other promises resolve using 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";
        }
    });
};

Then you will need to tweak the testing code so that it uses the promise instead of a setTimeout . Note that you can return a thenable object from the QUnit.test callback and it will automatically handle the resolving of a 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);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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