2015-01-27 17 views
6

Sto costruendo un modulo nodo e sto cercando di fare del mio meglio per testare l'unità. Ho configurato mocha e chai per fare il test di gestione. Sto riscontrando un problema durante il test dei miei metodi asincroni (metodi che restituiscono promesse).Assert sta interrompendo la funzione asincrona nel test del Mocha

Nel seguente test sto testando un metodo su un oggetto "Aggiornamento".

it('Should return a list of versions for the default git repo', function (done) { 
    fs.writeFileSync(appSetup.CONFIG_FILENAME, JSON.stringify(appSetup.DEFAULT_CONFIG)); 

    var upgrade = new Upgrade({ 
     quiet: true 
    }); 

    upgrade.getVersions().then(function (versions) { 
     assert(versions && versions.length > 0, 'Should have at least one version.'); 
     assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
     done(); 
    }, done); 
    }); 

Il getVersions() chiamata restituisce una promessa come il metodo è asincrono. Quando la promessa si risolve voglio testare il valore restituito nella variabile versions.

Il assert(versions && versions.length > 0, 'Should have at least one version.'); è il test effettivo. Ho aggiunto assert.equal(1, 2); perché ho notato che quando il test dovesse fallire il test case non compariva nemmeno nella lista dei test.

Suppongo che la chiamata di asserzione stia generando un'eccezione che Mocha dovrebbe prelevare. Tuttavia è rimasto intrappolato nella funzione di gestione delle promesse then.

Cosa sta succedendo qui? Perché quando l'affermazione sta per fallire in quel metodo non mostra il caso di test nella lista (non viene mostrato come fallito, come se non esistesse)?

risposta

11

Il nocciolo della questione è che il codice che hai è essenzialmente:

try { 
    var versions = upgrade.getVersions(); 
} catch (err){ 
    return done(err); 
} 

assert(versions && versions.length > 0, 'Should have at least one version.'); 
assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
done(); 

Guardando questo, dovrebbe essere chiaro che, se le asserzioni lanciate, quindi non verrà eseguita la richiamata.

try { 
    var versions = upgrade.getVersions(); 
    assert(versions && versions.length > 0, 'Should have at least one version.'); 
    assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
    done(); 
} catch (err){ 
    return done(err); 
} 

è più simile a quello che si vuole, che sarebbe:

upgrade.getVersions().then(function (versions) { 
    assert(versions && versions.length > 0, 'Should have at least one version.'); 
    assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
}).then(done, done); 

nodo che eseguirà le affermazioni e quindi spostare i callback in una secondaria .then() che sarà sempre gestire gli errori.

Detto questo, sarebbe molto più facile per tornare semplicemente la promessa come

return upgrade.getVersions().then(function (versions) { 
    assert(versions && versions.length > 0, 'Should have at least one version.'); 
    assert.equal(1, 2); // this throws the exception which causes the test case not even exist 
}); 

di lasciare Mocha monitorare la promessa stessa, senza la richiamata.

+0

Non sono sicuro di capire perché questa risposta funzioni. Il codice originale è fondamentalmente: async(). Then (function() { lanciare un nuovo errore(); // se questa linea genera, passa al gestore .catch() done(); }) .catch (done) // register done() come gestore degli errori. Se il lancio avviene, la chiamata 'done()' nel gestore 'then()' non viene eseguita, ma il gestore '.catch()' viene chiamato invece ... che è ancora 'done'. –

+0

Whoop, i commenti non consentono blocchi di codice e si bloccano dopo 5 minuti. Scusa per la formattazione di merda :( –

+0

'.then (fn, done)' non è equivalente a '.then (fn) .catch (done);', questo è il nocciolo della differenza. , è un errore non gestito, nel secondo esempio viene chiamato 'done'. – loganfsmyth

4

Il test non viene visualizzato nell'elenco finché non si chiama il callback, il che non avviene mai se tale affermazione fallisce. Dovresti chiamare lo .catch(done) sulla promessa finale per assicurarti che venga sempre chiamato done.

Il test sarà visualizzato se si assegna un valore di timeout, che probabilmente si dovrebbe fare.

Tutto ciò detto, mocha comprende le promesse. Non è necessario trattare con i callback a tutti:

it('Should return a list of versions for the default git repo', function() { 
    fs.writeFileSync(appSetup.CONFIG_FILENAME, JSON.stringify(appSetup.DEFAULT_CONFIG)); 

    var upgrade = new Upgrade({ 
     quiet: true 
    }); 

    return upgrade.getVersions().then(function (versions) { 
     assert(versions && versions.length > 0, 'Should have at least one version.'); 
     assert.equal(1, 2); 
    }); 
    }); 
+0

Vorrei poter accettare entrambe le vostre risposte! –

Problemi correlati