2012-01-26 8 views
12

me gustaría probar que la función siguiente realiza como se esperaba:¿Cómo puedo probar errores no detectados en mocha?

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

Aquí es mi intento:

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

Pero moka parece querer mantener ningún tipo de errores a sí mismo, y dejar mi prueba cuando los obtiene:

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) 

¿Alguna idea?

Respuesta

27

Actualización: Cortesía de Casey-adoptivo en un comentario a continuación:

A partir del v6.0.0 nodo puede utilizar process.prependOnceListener('uncaughtException', ...) hacer esto mucho más sucinta.


vieja respuesta:

El secreto está en process.listeners ('uncaughtException'):

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

basta con quitar el oyente moca, añada su propia, a continuación, vuelva a colocar el oyente moka.

ver más abajo:

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

Esto hizo el truco! Solo le haré una edición a su respuesta: debe restaurar el oyente original antes de hacer la afirmación, ya que la afirmación arroja un error. – Domenic

+0

Esto realmente debería estar en la documentación de Mocha! Me llevó una hora buscar en Google para encontrar esta respuesta. La captura no documentada de Mocha de errores (y pruebas fallidas), combinada con el hecho de que no se muestra ningún mensaje de error si no arrojas un objeto Error estándar (según los consejos de Crockford), es realmente difícil averiguar por qué la prueba está fallando. –

+7

Parece que en la última versión del nodo (v0.10.5 en el momento de este comentario) 'process.listeners (eventName)' devuelve una copia de la matriz de oyentes, por lo que no se llamará 'pop()' eliminar el oyente del emisor. Necesitará agregar la siguiente línea después del pop: 'process.removeListener ('uncaughtException', originalException);' –

0

Si el código asíncrono es ejecutada dentro de un dominio - y que es a menudo el caso - es necesario cambiar el oyente error en el dominio en lugar del proceso.

Para que se pueden utilizar:

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 en timoxley & Casey Foster, en v6 nodo ++

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

Esta sintaxis ('importación') no funciona en Node.js. – Domenic

+0

siempre puedes ejecutar mocha con '' '--require babel-core/register''' para tener' '' import/export''' y agregar el .babelrc con '' '{" presets ": [" es2015 "]}' '' – syarul

Cuestiones relacionadas