test spec node before async javascript node.js mocha chai

javascript - node - mocha spec



Mocha/Chai esperan.algo no captar los errores lanzados (5)

Estoy teniendo problemas para que Chai expect.to.throw Para expect.to.throw a trabajar en una prueba para mi aplicación node.js. La prueba sigue fallando en el error lanzado, pero si envuelvo el caso de prueba para intentar capturar y afirmar el error capturado, funciona.

¿ expect.to.throw no funcione como creo que debería o algo así?

it(''should throw an error if you try to get an undefined property'', function (done) { var params = { a: ''test'', b: ''test'', c: ''test'' }; var model = new TestModel(MOCK_REQUEST, params); // neither of these work expect(model.get(''z'')).to.throw(''Property does not exist in model schema.''); expect(model.get(''z'')).to.throw(new Error(''Property does not exist in model schema.'')); // this works try { model.get(''z''); } catch(err) { expect(err).to.eql(new Error(''Property does not exist in model schema.'')); } done(); });

La falla:

19 passing (25ms) 1 failing 1) Model Base should throw an error if you try to get an undefined property: Error: Property does not exist in model schema.


Como dice esta respuesta , también puedes envolver tu código en una función anónima como esta:

expect(function(){ model.get(''z''); }).to.throw(''Property does not exist in model schema.'');


Esta pregunta tiene muchos, muchos duplicados, incluyendo preguntas que no mencionan la biblioteca de afirmaciones de Chai. Aquí están los conceptos básicos reunidos:

La afirmación debe llamar a la función, en lugar de evaluarla de inmediato.

assert.throws(x.y.z); // FAIL. x.y.z throws an exception, which immediately exits the // enclosing block, so assert.throw() not called. assert.throws(()=>x.y.z); // assert.throw() is called with a function, which only throws // when assert.throw executes the function. assert.throws(function () { x.y.z }); // if you cannot use ES6 at work function badReference() { x.y.z }; assert.throws(badReference); // for the verbose assert.throws(()=>model.get(z)); // the specific example given. homegrownAssertThrows(model.get, z); // a style common in Python, but not in JavaScript

Puede verificar errores específicos usando cualquier biblioteca de aserciones:

Node

assert.throws(() => x.y.z); assert.throws(() => x.y.z, ReferenceError); assert.throws(() => x.y.z, ReferenceError, /is not defined/); assert.throws(() => x.y.z, /is not defined/); assert.doesNotThrow(() => 42); assert.throws(() => x.y.z, Error); assert.throws(() => model.get.z, /Property does not exist in model schema./)

Should

should.throws(() => x.y.z); should.throws(() => x.y.z, ReferenceError); should.throws(() => x.y.z, ReferenceError, /is not defined/); should.throws(() => x.y.z, /is not defined/); should.doesNotThrow(() => 42); should.throws(() => x.y.z, Error); should.throws(() => model.get.z, /Property does not exist in model schema./)

Chai espera

expect(() => x.y.z).to.throw(); expect(() => x.y.z).to.throw(ReferenceError); expect(() => x.y.z).to.throw(ReferenceError, /is not defined/); expect(() => x.y.z).to.throw(/is not defined/); expect(() => 42).not.to.throw(); expect(() => x.y.z).to.throw(Error); expect(() => model.get.z).to.throw(/Property does not exist in model schema./);

Debe manejar excepciones que ''escapan'' a la prueba

it(''should handle escaped errors'', function () { try { expect(() => x.y.z).not.to.throw(RangeError); } catch (err) { expect(err).to.be.a(ReferenceError); } });

Esto puede parecer confuso al principio. Como andar en bicicleta, simplemente ''hace clic'' para siempre una vez que hace clic.


Tienes que pasar una función para expect . Me gusta esto:

expect(model.get.bind(model, ''z'')).to.throw(''Property does not exist in model schema.''); expect(model.get.bind(model, ''z'')).to.throw(new Error(''Property does not exist in model schema.''));

La forma en que lo está haciendo, está pasando para expect el resultado de llamar a model.get(''z'') . Pero para probar si se arroja algo, debe pasar una función para expect , que expect se llamará a sí misma. El método de model.get utilizado anteriormente crea una nueva función que cuando se llama llamará a model.get con this conjunto al valor de model y el primer argumento establecido a ''z'' .

Una buena explicación de bind se puede encontrar here .


Y si ya está usando ES6 / ES2015, también puede usar una función de flecha. Básicamente es lo mismo que usar una función anónima normal pero más corta.

expect(() => model.get(''z'')).to.throw(''Property does not exist in model schema.'');


ejemplos de doc ...;)

porque confías en este contexto :

  • que se pierde cuando la función es invocada por .throw
  • no hay forma de que sepa lo que se supone que es

tienes que usar una de estas opciones:

  • envolver el método o llamar a la función dentro de otra función
  • enlazar el contexto

    // wrap the method or function call inside of another function expect(function () { cat.meow(); }).to.throw(); // Function expression expect(() => cat.meow()).to.throw(); // ES6 arrow function // bind the context expect(cat.meow.bind(cat)).to.throw(); // Bind