2017-05-25 4 views
0

ich den folgenden Code verwendet haben:Testing verspricht innerhalb Versprechen

function makeCall(userInfo) { 
    api.postUser(userInfo).then(response => { 
    utils.redirect(response.url); 
    }) 

    // other logic 
    return somethingElse; 
} 

Und ich war in der Lage, einen Test zu schreiben, der so aussah:

const successPromise = Promise.resolve({ url: 'successUrl' }) 

beforeEach(function() { 
    sinon.stub(api.postUser).returns(successPromise); 
} 

afterEach(function() { 
    api.postUser.restore(); 
} 

it "calls API properly and redirects" do 
    makeCall({}); 
    expect(api.postUser).calledWith(userInfo).toBe(true); 
    successPromise.then(() => { 
    expect(utils.redirect.calledWith('successUrl')).toBe(true); 
    done(); 
    } 
emd 

Und alles war grün.

Nun hatte ich ein weiteres Versprechen fügen Sie eine weiteren externen Anruf zu tätigen, bevor Sie den api postUser Anruf zu tun, so dass mein Code wie folgt aussieht:

function makeCall(names) { 
    fetchUserData(names).then(userData => { 
    return api.postUser(userData).then(response => { 
    utils.redirect(response.url); 
    }) 
    }) 

    // other logic 
    return somethingElse; 
} 

wo fetchUseData eine Kette von vielen Versprechungen ist, so wie :

function fetchNames(names) { 
    // some name regions 
    return Promise.all(names); 
} 
function fetchUserData(names) { 
    fetchUsersByNames(names).then(users => { 
    // For now we just choose first user 
    { 
     id: users[0].id, 
     name: users[0].name, 
    } 
    }); 
} 

Und die Tests, die ich hatte, scheitern. Ich versuche zu verstehen, wie ich meine Tests ändern kann, um sicherzustellen, dass ich immer noch teste, dass ich den letzten API-Aufruf richtig ausführe und die Weiterleitung ebenfalls erfolgt. Ich möchte stumm was fetchUserData(names), um diesen HTTP-Aufruf zu verhindern.

+0

Sie verwenden nicht richtig Versprechungen. Ihr Code hat keine einzige 'return'-Anweisung, wenn sie mehrere haben sollte (oder zumindest Pfeilfunktionen verwenden sollte, so dass Sie sie nicht brauchen, was Sie nicht tun). Sie beziehen sich auf einen frei schwebenden Code als "Mein Code". Wie nennt man diesen Code? Sollten nicht Ihre Tests es nennen? Sie scheinen ein Ergebnis zu beobachten, nachdem Ihr Code bereits irgendwo anders ausgeführt wurde. – JLRishe

+0

Versuchen Sie, das innere Versprechen (add 'return') zurückzugeben, um eine Versprechenskette zu erstellen. – TiagoLr

+0

@JLRishe aktualisiert. Mein Hauptanliegen ist, wo sollte ich das 'done()' machen oder was soll ich tun, damit die Versprechen niedergeschrieben und ausgewertet werden. –

Antwort

0

Sie verwenden nicht richtig Versprechungen. Ihr Code hat keine einzige return Anweisung, wenn es mehrere haben sollte (oder es sollte Pfeilfunktionen verwenden, so dass Sie sie nicht brauchen, was Sie nicht tun).

Fix Code:

function makeCall(names) { 
    // v---- return 
    return fetchUserData(names).then(userData => { 
    // v---- return 
    return api.postUser(userData).then(response => { 
     utils.redirect(response.url); 
    }) 
    }) 
} 


function fetchUserData(names) { 
    // v---- return 
    return fetchUsersByNames(names).then(users => { 
    // For now we just choose first user 
    // v---- return 
    return { 
     id: users[0].id, 
     name: users[0].name, 
    } 
    }); 
} 

Sobald Sie das getan haben, können Sie Ihre Test warten auf alle Operationen haben zu beenden.

Prüfregeln:

makeCall(['name']).then(() => 
    expect(api.postUser).calledWith(userInfo).toBe(true); 
    expect(utils.redirect.calledWith('successUrl')).toBe(true); 
    done(); 
}); 
+0

hey JLRishe, was passiert, wenn ich nicht will, das Versprechen in der äußersten Funktion zurückzukehren? Es ist ein Nebeneffekt, und ich möchte etwas anderes (der Grund dafür zurückzukehren ist, dass dies in einer redux Middleware verwendet wird, und Sie müssen immer die 'nächste (Aktion)' zurückzukehren. Ich habe meine Frage bearbeitet zu erklären, warum ich nicht an diesem letzten Versprechen eine Rückkehr haben, sondern behandeln sie als Nebenwirkung der Funktion. –

+0

@HommerSmith es klingt wie Sie zwei unvereinbare Paradigmen mischen könnten versuchen. es ist wie redux Middleware sieht hat seine eigene Art und Weise des Umgangs mit Asynchronität, die von Versprechungen sehr anders. Leider, ich weiß nichts über redux Middleware, aber [hier einige Informationen über die Verwendung es mit dem Versprechen] (https://www.google.co.jp/search?q=redux+ Middleware + Versprechungen & oq = redux + Middleware + Versprechungen & aqs = chrome..69i64.4271j0j4 & sourceid = chrome & ie = UTF-8). – JLRishe

+0

Danke JLRishe. Ich denke, da meine Tests bestanden haben, hatte ich gerade ein Versprechen (auch wenn es nicht zurückkam), Ich dachte, dass, wenn ich mehr Versprechungen in diesem anfänglichen p hinzufügte Romise, ich könnte es herausfinden. –

0

Sie sollten eine return-Anweisung hinzufügen, sonst werden Sie keine Versprechungen Rückkehr nirgendwo:

function fetchNames(names) { 
    // some name regions 
    return Promise.all(names); 
} 
function fetchUserData(names) { 
    return fetchUsersByNames(names).then(users => { 
    // For now we just choose first user 
    { 
     id: users[0].id, 
     name: users[0].name, 
    } 
    }); 
} 

Also, wenn Sie verwenden Promise.all(), dann werden Sie als Ergebnis der Versprechen mit allen ein Array der Wert, der von allen Versprechen zurückgegeben wird. So dann sollte diese Methode wie folgt aussehen, wenn sie aufgerufen:

fetchNames(names).then((arrayOfResolvedPromises) => { 
// here you will have all your promised resolved and the array holds all the results 
}); 

So in Ihrem Test können Sie innerhalb des Blocks, wo alle die Versprechungen gelöst werden getan bewegen.

Zusätzlich empfehle ich Ihnen dringend, eine Bibliothek als Chai-as-Versprochen für das Testen von Versprechen zu verwenden. Es hat viele schöne Methoden zum Testen Ihrer Versprechen.

https://github.com/domenic/chai-as-promised

+0

Das macht meine Tests nicht bestanden. Wo soll ich das "done()" setzen, wenn ich mehrere Versprechen habe? –

+0

Sie müssen alle Versprechen in einem Promise.all() halten. Innerhalb seiner dann sperren Sie sind sicher, dass alle Versprechungen wurden gelöst – quirimmo