问题
I have a mongoose schema method that inserts a new record then returns an activation code. In my tests I want to call this method then run a query that verifies some things about the record it has added. The problem is the method returns before the record has become visible to the subsequent query, even though I am awaiting the .save before returning.
I have verified this by adding a delay between the method call and the subsequent query. Without the delay the second query returns null. With a delay of above ~30ms the query returns what I was expecting and the test passes.
I don't think such a short delay will cause any problems in production but how can I account for it in my tests without resorting to ugly and arbitrary setTimouts? Is there a way to make the call to .save run and return synchronously in my tests? Or is there an event I can listen for which fires when the data has been written. Or am I thinking about this all wrong?
// My method
userSchema.statics.addNewUser = async function (params) {
const randomSlug = cryptoRandomString({ length: 64, type: "url-safe" })
const hashedPassword = await bcrypt
.genSalt(10)
.then(salt => bcrypt.hash(params.password, salt))
const user = new User({
name: params.name,
email: params.email,
password: hashedPassword,
active: false,
activationCode: randomSlug
})
await user.save((err) => { if (err) throw(err)})
return randomSlug
}
// My test
it("Should create a new account and return an activation code", async () => {
const activationCode = await User.addNewUser({
name: "Bob",
email: "Bob@iscool.com",
password: "password",
})
assert.match(activationCode, /^.{64}$/)
// Result is null unless there is a delay of ~30ms here
const query = User.findOne({ activationCode })
query.select("name email active password")
const result = await query.exec()
console.log("RESULT IS:", result)
assert(result)
})
回答1:
Mongoose supports a dual promise and callback API.
Supplying a callback function to Model.prototype.save() returns undefined
instead of a Promise
, so the await
returns immediately.
await user.save()
Rejected promises will be thrown automatically by the async
functions.
来源:https://stackoverflow.com/questions/63124330/how-to-deal-with-schema-save-delay-in-mongoose-tests