unitarios unitarias test spec pruebas nodejs node framework node.js promise mocha chai

node.js - test - pruebas unitarias node js



¿Cómo pruebo adecuadamente las promesas con mocha y chai? (4)

La siguiente prueba se comporta de manera extraña:

it(''Should return the exchange rates for btc_ltc'', function(done) { var pair = ''btc_ltc''; shapeshift.getRate(pair) .then(function(data){ expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); done(); }) .catch(function(err){ //this should really be `.catch` for a failed request, but //instead it looks like chai is picking this up when a test fails done(err); }) });

¿Cómo debo manejar adecuadamente una promesa rechazada (y probarla)?

¿Cómo debo manejar adecuadamente una prueba fallida (es decir: expect(data.rate).to.have.length(400);

Aquí está la implementación que estoy probando:

var requestp = require(''request-promise''); var shapeshift = module.exports = {}; var url = ''http://shapeshift.io''; shapeshift.getRate = function(pair){ return requestp({ url: url + ''/rate/'' + pair, json: true }); };


Aquí está mi opinión:

  • usando async/await
  • no necesita módulos chai adicionales
  • evitando el problema de captura, @TheCrazyProgrammer señaló anteriormente

Una función de promesa retrasada, que falla, si se le da un retraso de 0:

const timeoutPromise = (time) => { return new Promise((resolve, reject) => { if (time === 0) reject({ ''message'': ''invalid time 0'' }) setTimeout(() => resolve(''done'', time)) }) } // ↓ ↓ ↓ it(''promise selftest'', async () => { // positive test let r = await timeoutPromise(500) assert.equal(r, ''done'') // negative test try { await timeoutPromise(0) // a failing assert here is a bad idea, since it would lead into the catch clause… } catch (err) { // optional, check for specific error (or error.type, error. message to contain …) assert.deepEqual(err, { ''message'': ''invalid time 0'' }) return // this is important } assert.isOk(false, ''timeOut must throw'') log(''last'') })

La prueba positiva es bastante simple. La falla inesperada (simulación por 500→0 ) fallará la prueba automáticamente, ya que la promesa rechazada aumenta.

La prueba negativa usa la idea try-catch-idea. Sin embargo: ''quejarse'' sobre un pase no deseado ocurre solo después de la cláusula catch (de esa manera, no termina en la cláusula catch (), lo que desencadena más errores pero engañosos.

Para que esta estrategia funcione, uno debe devolver la prueba de la cláusula catch. Si no desea probar nada más, use otro bloque it ().


Como ya se señaló here , las versiones más nuevas de Mocha ya son compatibles con Promise. Pero dado que el OP preguntó específicamente sobre Chai, es justo señalar el paquete chai-as-promised que proporciona una sintaxis limpia para probar las promesas:

usando chai-como-prometió

A continuación, le mostramos cómo puede usar chai-as-prometido para probar los casos de resolve y reject de una promesa:

var chai = require(''chai''); var expect = chai.expect; var chaiAsPromised = require("chai-as-promised"); chai.use(chaiAsPromised); ... it(''resolves as promised'', function() { return expect(Promise.resolve(''woof'')).to.eventually.equal(''woof''); }); it(''rejects as promised'', function() { return expect(Promise.reject(''caw'')).to.be.rejectedWith(''caw''); });

sin chai según lo prometido

Para dejar en claro lo que se está probando, aquí está el mismo ejemplo codificado sin chai-como-prometió:

it(''resolves as promised'', function() { return Promise.resolve("woof") .then(function(m) { expect(m).to.equal(''woof''); }) .catch(function(m) { throw new Error(''was not supposed to fail''); }) ; }); it(''rejects as promised'', function() { return Promise.reject("caw") .then(function(m) { throw new Error(''was not supposed to succeed''); }) .catch(function(m) { expect(m).to.equal(''caw''); }) ; });


Hay una mejor solución. Simplemente devuelva el error con hecho en un bloque catch.

// ... it(''fail'', (done) => { // any async call that will return a Promise ajaxJson({}) .then((req) => { expect(1).to.equal(11); //this will throw a error done(); //this will resove the test if there is no error }).catch((e) => { done(e); //this will catch the thrown error }); });

esta prueba fallará con el siguiente mensaje: AssertionError: expected 1 to equal 11


Lo más fácil sería utilizar el soporte de promesas incorporado que Mocha tiene en las versiones recientes:

it(''Should return the exchange rates for btc_ltc'', function() { // no done var pair = ''btc_ltc''; // note the return return shapeshift.getRate(pair).then(function(data){ expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); });// no catch, it''ll figure it out since the promise is rejected });

O con Nodo moderno y asíncrono / espera:

it(''Should return the exchange rates for btc_ltc'', async () => { // no done const pair = ''btc_ltc''; const data = await shapeshift.getRate(pair); expect(data.pair).to.equal(pair); expect(data.rate).to.have.length(400); });

Dado que este enfoque es una promesa de principio a fin, es más fácil de probar y no tendrá que pensar en los casos extraños en los que está pensando, como las llamadas impares de done() todas partes.

Esta es una ventaja que Mocha tiene sobre otras bibliotecas como Jasmine en este momento. También es posible que desee verificar Chai As Promised, lo que lo haría aún más fácil (no .then ), pero personalmente prefiero la claridad y simplicidad de la versión actual