Master the correct use of chai test.catch() block
P粉242535777
2023-09-02 12:25:27
<p>I'm trying to achieve good coverage with end-to-end testing of my code base, so I want to test the <code>.catch()</code> code as well. </p><p>
My API uses node.js and mongoose. </p><p>
I use chai and mocha for testing.</p>
<p>I tried something like: </p>
<p><em>File 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) {
//This is the code I want to test
console.error(`Error finding user ${req.name}:`, err);
return res.status(err.code).json({ message: err });
}
}</pre>
<p><em>File 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>File 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 errors should be handled", function() {
describe("Problematic User.findOne method", function() {
const _User_findOne_Backup = User.findOne;
beforeEach(function() {
// This function should override the real findOne function, but it didn't succeed!User.findOne = function() {
return Promise.reject("Forced error");
};
});
afterEach(function() { //Restore the real function after each test
User.findOne = _User_findOne_Backup;
});
it("Registration should return a server error", 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>The problem is that in my tests, the fake <code>User.findOne()</code> method is never called: the original mongoose <code>findOne</code> method is called successfully , so the <code>getUser</code> method never throws an exception, causing my test to fail...</p>
<p>Maybe I'm missing something obvious, but I really can't find it... :-(</p><p>
If more code or context is needed, please let me know...</p>
<p><strong>Update: </strong>
Following @Bergi's suggestion, I added complete information about my (simplified) model and required modules...</p>
Works great for me.
For example:
user.model.js
:user.controller.js
:server.js
:user.test.js
:Test Results:
Package version: