2012-01-26 12 views
12

Vorrei verificare che la seguente funzione esegue come previsto:Come posso testare gli errori non rilevati in mocha?

function throwNextTick(error) { 
    process.nextTick(function() { 
     throw error; 
    }); 
} 

Ecco il mio tentativo:

describe("throwNextTick", function() { 
    it("works as expected", function (next) { 
     var error = new Error("boo!"); 
     var recordedError = null; 
     process.once("uncaughtException", function (error) { 
      recordedError = error; 
     }); 

     throwNextTick(error); 

     process.nextTick(function() { 
      recordedError.should.be(error); 
      next(); 
     }); 
    }); 
}); 

Ma moka sembra voler mantenere eventuali errori a se stesso, e non riescono mia prova quando li ottiene:

C:\Users\ddenicola\Programming (Synced)\pubit>mocha test/basicTest.js 

    throwNextTick 
    0) works as expected 

    ? 1 of 1 tests failed: 

    1) throwNextTick works as expected: 
    Error: boo! 
     at Test.fn (C:\Users\ddenicola\Programming (Synced)\pubit\test\basicTest.js:11:21) 
     at Test.run (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runnable.js:144:15) 
     at Runner.runTest (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:271:10) 
     at C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:315:12 
     at next (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:199:14) 
     at C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:208:7 
     at next (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:157:23) 
     at Array.0 (C:\Users\ddenicola\AppData\Roaming\npm\node_modules\mocha\lib\runner.js:176:5) 
     at EventEmitter._tickCallback (node.js:192:40) 

Qualche idea?

risposta

27

Aggiornamento: Per gentile concessione di casey-adottiva in un commento qui sotto:

A partire dal nodo v6.0.0 è possibile utilizzare process.prependOnceListener('uncaughtException', ...) per fare questo molto più succintamente.


Vecchia risposta:

Il segreto sta nel process.listeners ('uncaughtException'):

http://nodejs.org/docs/latest/api/events.html#emitter.listeners

è sufficiente rimuovere l'ascoltatore moka, aggiungere il proprio, quindi ricollegare l'ascoltatore di moka.

vedere qui sotto:

var assert = require('assert') 

function throwNextTick(error) { 
    process.nextTick(function() { 
     throw error 
    }) 
} 


describe("throwNextTick", function() { 
    it("works as expected", function (next) { 
     var error = new Error("boo!") 
     var recordedError = null 
     var originalException = process.listeners('uncaughtException').pop() 
     //Needed in node 0.10.5+ 
     process.removeListener('uncaughtException', originalException); 
     process.once("uncaughtException", function (error) { 
      recordedError = error 
     }) 
     throwNextTick(error); 
     process.nextTick(function() { 
      process.listeners('uncaughtException').push(originalException) 
      assert.equal(recordedError, error) 
      next() 
     }) 
    }) 
}) 
+1

Questo ha fatto il trucco! Solo una modifica farò per la tua risposta: è necessario ripristinare il listener originale prima di fare l'asserzione, poiché l'assert genera un errore. – Domenic

+0

Questo dovrebbe essere nella documentazione di Mocha! Mi ci è voluta un'ora per cercare la risposta. Cattura di errori non documentati di Mocha (e test falliti), combinato con il fatto che non viene mostrato alcun messaggio di errore se non si lancia un oggetto Error standard (secondo il consiglio di Crockford), rende è davvero difficile capire perché il test sta fallendo. –

+7

Sembra che nell'ultima versione del nodo (v0.10.5 al momento di questo commento) 'process.listeners (eventName)' restituisca una copia dell'array listeners, e quindi chiamare 'pop()' su di esso in realtà non rimuovere l'ascoltatore dall'emettitore. Sarà necessario aggiungere la seguente riga dopo il pop: 'process.removeListener ('uncaughtException', originalException);' –

0

Se il codice asincrono è eseguito all'interno di un dominio - e che è spesso il caso - è necessario modificare l'ascoltatore errore sul dominio invece del processo.

per questo si può usare:

it('should produce an unhandled exception', function (done) { 

    // Remove Mocha's error listener 
    var originalErrorListeners = process.domain.listeners('error'); 
    process.domain.removeAllListeners('error'); 

    // Add your own error listener to check for unhandled exceptions 
    process.domain.on('error', function() { 

     // Add the original error listeners again 
     process.domain.removeAllListeners('error'); 
     for (var i = 0; i < originalErrorListeners.length; i+=1) { 
      process.domain.on('error', originalErrorListeners[i]); 
     } 

     // For the sake of simplicity we are done after catching the unhandled exception 
     done(); 

    }); 

    // This would be your async application code you expect to throw an exception 
    setTimeout(function() { 
     throw new Error(); 
    }); 

}); 
-1

Base sul timoxley & Casey Foster, nel nodo v6 ++

const assert = require('assert') 

describe('throwNextTick', function() { 
    it('works as expected', function(next) { 

     function cb(err) { 
      assert.equal(err instanceof Error, true) 
      next() 
     } 

     function test(){ 
      process.nextTick(() => { 
       throw new Error('err') 
      }) 
     } 

     process.prependOnceListener('uncaughtException', cb) 
     test() 

    }) 
}) 
+0

Questa sintassi ('import') non funziona in Node.js. – Domenic

+0

potresti sempre eseguire mocha con '' '--require babel-core/register''' per avere"/import/export''' e aggiungere .babelrc con '' '{" preset ": [" es2015 "]}' '' – syarul

Problemi correlati