2017-01-17 1 views
3

Ich bin ziemlich neu in der Welt von Javascript und asynchron und es scheint, dass beide Kopfschmerzen geben.Asynchrones Javascript mit Promises und Unit/Integration Tests

Also, ich habe einen 3rd-Party-Client-API, die die folgenden async Methode hat getItem(id)

Jetzt auf seinen Kindern Ich versuche, den Status für ein übergeordnetes Element zu bestimmen:

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

Dann Um sicherzugehen, dass ich unterwegs nichts kaputt machen kann, habe ich mich für einige Integrationstests entschieden, also habe ich mich für QUnit und 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); 
}); 
entschieden

versucht, die setTimeout Timeout, versucht mit assert.async(2) und assert.async();, der Standardwert pro QUnit pro ihre Dokumentation, aber nichts nützt, ist das Endergebnis immer noch das gleiche und auch nach einer Reihe von Lesungen und versuchen zu verstehen, ich habe keine Ahnung, was ich falsch mache:

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

tun, um die 'getItem (id)' müssen Anrufe in Reihe oder parallel –

+0

@JaromandaX Keine der Versprechungen verwenden Ergebnisse aus anderen Versprechungen gemacht werden, also würde ich parallel sagen. – 4castle

+0

aus dem Code geschrieben, dass eine vernünftige Annahme scheint - aber man kennt nicht die Innereien einer unbenannten 3rd Party API: p –

Antwort

4

Ihre getStatus Funktion ein Ergebnis zurückgibt, bevor eine von der Asynchron-resolve nennt. Sie müssen getStatus ein Versprechen zurück, die, wenn alle anderen Versprechen löst Promise.all mit beheben:

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

Dann müssen Sie den Test-Code optimieren, so dass er das Versprechen statt eines setTimeout verwendet. Beachten Sie, dass Sie ein rennbares Objekt aus dem Callback QUnit.test zurückgeben können, und es wird automatisch die Auflösung eines Promise behandeln.

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