异步函数的 chai 测试失败抛出错误
Failing chai test for async function throwing an error
我想测试一下我的 "missing_body" 是否被抛出。但我的测试只显示已捕获的错误,但 expect 测试仍然失败。你能帮我理解一下吗?
async add(req) {
const db = _.get(req, 'app.locals.db');
const bookDescription = req.body;
logger.info('books.add', bookDescription);
if (_.isEmpty(bookDescription)) {
throw new Error('missing_body');
}
[...]
}
describe('+add(req)', function() {
it('should fail because of missing body', async function() {
const req = {
body: {},
};
expect(await this.ctrl.add(req)).to.throw(new Error('missing_body'));
});
});
如果您希望捕获一些错误,您将需要在捕获块内断言。您正在尝试断言创建新 Error 实例的错误。如果您使用的是同步编程,那么您需要捕获如下错误:
it('should fail because of missing body', async function() {
const req = {
body: {},
};
try {
await this.ctrl.add(req)
} catch(e) {
expect(e.message).to.equal('missing_body');
}
});
另一个错误是提供对象方法(或依赖于此的任何 stand-alone 函数)作为断言的目标。这样做是有问题的,因为当函数被 .throw 调用时,this 上下文将丢失;它无法知道这应该是什么。有两种方法可以解决这个问题。一种解决方案是将方法或函数调用包装在另一个函数中。另一种解决方案是使用绑定。如果你测试同步功能。
expect(function () { cat.meow(); }).to.throw(); // Function expression
expect(() => cat.meow()).to.throw(); // ES6 arrow function
expect(cat.meow.bind(cat)).to.throw(); // Bind
但在异步中 (await add()).to.throw(Error)
永远不会工作:如果 fails() 拒绝,则会抛出错误,并且永远不会执行 .to.throw(Error)。所以你需要做这样的事情:
it('should fail', async () => {
await expect(this.ctrl.add(req.body)).to.be.rejectedWith(Error);
})
解决方案:
async add(req) {
const db = _.get(req, 'app.locals.db');
const bookDescription = req.body;
logger.info('books.add', bookDescription);
if (_.isEmpty(bookDescription)) {
throw new Error('missing_body');
}
[...]
}
describe('+add(req)', function() {
it('should fail because of missing body', async function() {
const req = {
body: {},
};
await expect(this.ctrl.add(req.body)).to.be.rejectedWith(Error);
});
});
我想测试一下我的 "missing_body" 是否被抛出。但我的测试只显示已捕获的错误,但 expect 测试仍然失败。你能帮我理解一下吗?
async add(req) {
const db = _.get(req, 'app.locals.db');
const bookDescription = req.body;
logger.info('books.add', bookDescription);
if (_.isEmpty(bookDescription)) {
throw new Error('missing_body');
}
[...]
}
describe('+add(req)', function() {
it('should fail because of missing body', async function() {
const req = {
body: {},
};
expect(await this.ctrl.add(req)).to.throw(new Error('missing_body'));
});
});
如果您希望捕获一些错误,您将需要在捕获块内断言。您正在尝试断言创建新 Error 实例的错误。如果您使用的是同步编程,那么您需要捕获如下错误:
it('should fail because of missing body', async function() {
const req = {
body: {},
};
try {
await this.ctrl.add(req)
} catch(e) {
expect(e.message).to.equal('missing_body');
}
});
另一个错误是提供对象方法(或依赖于此的任何 stand-alone 函数)作为断言的目标。这样做是有问题的,因为当函数被 .throw 调用时,this 上下文将丢失;它无法知道这应该是什么。有两种方法可以解决这个问题。一种解决方案是将方法或函数调用包装在另一个函数中。另一种解决方案是使用绑定。如果你测试同步功能。
expect(function () { cat.meow(); }).to.throw(); // Function expression
expect(() => cat.meow()).to.throw(); // ES6 arrow function
expect(cat.meow.bind(cat)).to.throw(); // Bind
但在异步中 (await add()).to.throw(Error)
永远不会工作:如果 fails() 拒绝,则会抛出错误,并且永远不会执行 .to.throw(Error)。所以你需要做这样的事情:
it('should fail', async () => {
await expect(this.ctrl.add(req.body)).to.be.rejectedWith(Error);
})
解决方案:
async add(req) {
const db = _.get(req, 'app.locals.db');
const bookDescription = req.body;
logger.info('books.add', bookDescription);
if (_.isEmpty(bookDescription)) {
throw new Error('missing_body');
}
[...]
}
describe('+add(req)', function() {
it('should fail because of missing body', async function() {
const req = {
body: {},
};
await expect(this.ctrl.add(req.body)).to.be.rejectedWith(Error);
});
});