掌握chai测试.catch()块的正确使用方法
P粉242535777
2023-09-02 12:25:27
<p>我正在努力通过我的代码库的端到端测试来实现良好的覆盖率,所以我也想测试 <code>.catch()</code> 代码。</p><p>
我的API使用node.js和mongoose。</p><p>
我使用chai和mocha进行测试。</p>
<p>我尝试了类似以下的代码:</p>
<p><em>文件 src/controllers/user.controller.js:</em></p>
<pre class="brush:php;toolbar:false;">const User = require("../models/user.model");
const getUser = async(req, res) => {
try {
const user = await User.findOne({name: req.name});
return res.status(200).json(user);
} catch (err) {
// 这是我想要测试的代码
console.error(`查找用户 ${req.name} 时出错:`, err);
return res.status(err.code).json({ message: err });
}
}</pre>
<p><em>文件 src/models/user.model.js:</em></p>
<pre class="brush:php;toolbar:false;">const mongoose = require("mongoose");
const UserSchema = mongoose.Schema({
name: {
type: String,
required: "Name is required",
},
});
module.exports = mongoose.model("User", UserSchema);</pre>
<p><em>文件 test/user.test.js:</em></p>
<pre class="brush:php;toolbar:false;">const chai = require("chai");
const chaiHttp = require("chai-http");
const spies = require("chai-spies");
const User = require("../src/models/user.model");
chai.use(chaiHttp);
chai.use(spies);
chai.should();
describe("应处理mongoose错误", function() {
describe("有问题的User.findOne方法", function() {
const _User_findOne_Backup = User.findOne;
beforeEach(function() {
// 这个函数应该重载真正的findOne函数,但它没有成功!User.findOne = function() {
return Promise.reject("强制错误");
};
});
afterEach(function() { // 每个测试后恢复真正的函数
User.findOne = _User_findOne_Backup;
});
it("注册应该返回服务器错误", function() {
const spy = chai.spy();
return chai
.request(server)
.post("/api/getUser")
.send({name: "Alice"})
.then(spy)
.catch((err) => {
const res = err.response;
res.should.have.status(500);
})
.then(() => {
spy.should.not.have.been.called();
})
;
});
});
});</pre>
<p>问题是在我的测试中,伪造的 <code>User.findOne()</code> 方法从未被调用:原始的mongoose <code>findOne</code> 方法被调用成功,所以 <code>getUser</code> 方法从不抛出异常,导致我的测试失败...</p>
<p>可能我漏掉了一些明显的东西,但我真的找不到它... :-(</p><p>
如果需要更多的代码或上下文,请告诉我...</p>
<p><strong>更新:</strong>
根据 @Bergi 的建议,我添加了关于我的(简化的)模型和所需模块的完整信息...</p>
对我来说很好用。
例如:
user.model.js
:user.controller.js
:server.js
:user.test.js
:测试结果:
软件包版本: