Testing mongoose pre-save hook Testing mongoose pre-save hook mongoose mongoose

Testing mongoose pre-save hook


Before we start: I'm looking for the same thing as you do and I've yet to find a way to test the different hooks in Mongoose without a database. It's important that we distinguish between testing our code and testing mongoose.

Validation is middleware. Mongoose registers validation as a pre('save') hook on every schema by default. http://mongoosejs.com/docs/validation.html

Considering that validate will always be added to the model and I wish to test the automated fields in my model, I've switched from save to validate.

UserSchema = new Schema({  email: {type: String, required: true},  password: {type: String, required: true}    });UserSchema.pre('validate', function(next) {  const user = this;  user.email = user.email.toLowerCase();  // for testing purposes  console.log("Pre validate hook called");  next();});

The test will now look like:

it("should convert email to lower case before saving", (done) => {    const user = new User({email: "VALID@EMAIL.COM", password: "password123"});    assert.equal(res.email,"valid@email.com");}

So What About the Pre Save Hook?

Because I've moved the business logic for automatic fields from 'save' to 'validate', I'll use 'save' for database specific operations. Logging, adding objects to other documents, and so on. And testing this only makes sense with integration with a database.


I just faced the same issue and managed to solve it by extracting the logic out of the hook, making it possible to test it in isolation. With isolation I mean without testing anything Mongoose related.

You can do so by creating a function, that enforces your logic, with the following structure:

function preSaveFunc(next, obj) {  // your logic  next();}

You can then call it in your hook:

mySchema.pre('save', function (next) { preSaveFunc(next, this); });

This will make the reference to this available inside the function, so you can work with it.

The extracted part can then be unit tested by overwriting the next function to a function without a body.

Hope this will help anyone as it actually was a pain to solve this with my limited knowledge on Mongoose.