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:
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.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./)
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