2016-11-12 1 views
1

Ich verwende mocha, um eine Reihe von Integrationstests gegen einen externen Webservice durchzuführen. Ich verwende superagent-promise für die Anfrage/Antwort-Behandlung, und ich verwende expect als meine Assertion-Bibliothek.Mocha Tests mit Superagenten + verspricht Timeout anstatt mit 'expect' zu scheitern

Für einige dieser Tests muss ich eine große Anzahl von Anfragen zusammenketten, also waren die Versprechen sehr hilfreich. Allerdings merke ich, dass meine Tests jetzt mit einem Timeout (und keine Fehlermeldung) statt mit der Fehlermeldung selbst fehlschlagen. Als ein einfaches Beispiel:

it('[MESSAGES-1] cannot be posted without an auth token', function(done) { 
    agent.post(config.webRoot + '/rooms/ABC/messages').send({ 
     content: 'This is a test!' 
    }).end().then(function(res) { 
     // Not expected 
    }, function(err) { 
     expect(err.status).toBe(401) 
     done() 
    }) 
    }) 

funktioniert wie erwartet und übergibt:

Messages 
    ✓ [MESSAGES-1] cannot be posted without an auth token 

jedoch, wenn ich meine Behauptung ändern einen anderen Statuscode zu erwarten:

expect(err.status).toBe(200) // This should fail 

Dann wird der Test scheitert mit einer Zeitüberschreitung!

1) Messages [MESSAGES-1] cannot be posted without an auth token: 
    Error: timeout of 1000ms exceeded. Ensure the done() callback is being called in this test. 

Ist dies ein häufiges Problem? Gibt es einen Workaround oder Tweak, den ich machen kann? Ich möchte nicht die Fähigkeit verlieren, Versprechungen zu verwenden.

Antwort

2

Ist dies ein bekanntes Problem?

Dies ist eigentlich kein Problem.

Das Problem ist, dass expect(err.status).toBe(200) einen Fehler auslöst, der innerhalb der .then geschluckt wird und der Code niemals done() erreicht.

it('[MESSAGES-1] cannot be posted without an auth token', function(done) { 
    agent.post(config.webRoot + '/rooms/ABC/messages').send({ 
     content: 'This is a test!' 
    }).end() 

    .then(function(res) { 
     // Not expected 
    }, function(err) { 
     expect(err.status).toBe(401) 
     done() 
    }) 
    .catch(function(err) { 
     done(err); //report error thrown in .then 
    }) 
    }) 

diese Weise können Sie fangen und melden Sie den Fehler von expect(err.status).toBe(200) geworfen: Sie sollten Sie Code wie folgt neu strukturieren.

+0

Das war es! Ich bin neu in Versprechungen in JavaScript - ich war mir der 'catch()' nicht bewusst, aber das funktioniert perfekt. –

2

In Ihrem Fall tritt das Zeitlimit auf, weil der done Callback nie aufgerufen wird, entweder weil die HTTP-Anforderung nicht fehlgeschlagen ist oder die Erwartung fehlgeschlagen ist, so dass ein Assertion-Fehler ausgegeben wurde.

Mocha behandelt ordnungsgemäße (versprechen, zurück) asynchrone Tests, also nicht den done Callback verwenden, verursacht es Verwirrung, wenn mit Versprechen vermischt. Gib das Versprechen zurück:

it('[MESSAGES-1] cannot be posted without an auth token', function() { 
    return agent.post(config.webRoot + '/rooms/ABC/messages').send({ 
    content: 'This is a test!' 
    }).end().then(function(res) { 
    // here you must throw an error, because if the post didnt fail somehow, the test would be green because of no assertations and no promise rejection. 
    throw new Error("Not expected"); 
    }, function(err) { 
    expect(err.status).toBe(401); 
    }); 
}); 
+0

"* ... entweder weil die HTTP - Anfrage nicht fehlgeschlagen ist ... *" OP gibt ausdrücklich an, dass die einzige Änderung, die er an dem Code vornimmt, 'expect (err.status) .toBe (401)' to 'expect (err .status) .zuBe (200) '. Basierend auf dieser Prämisse besteht das Problem darin, dass der geworfene Assertionsfehler die Ausführung des Codes innerhalb des '.then'-Versprechens anhält - ein Fehler, der im OP-Code durch das Versprechen verschlungen wird (wie in meiner Antwort angegeben). – rabbitco

+0

@rabbitco Deshalb solltest du 'done' nicht verwenden, wenn du mit Versprechungen arbeitest, und lass Mocha sie richtig behandeln. – robertklep

+0

@robertklep: vereinbart – rabbitco