Beforehand, thank you for any help/advice you can provide!
I'm trying to find an elegant way to test the date/time when creating an instance of a Mongoose model.
I'd like to make sure that the time that is stored is the correct time.
My model currently looks like this:
const messageSchema = mongoose.Schema({
user: { type: String, required: true },
message: { type: String, required: true },
created: { type: Date, default: Date.now },
});
const Message = mongoose.model('Message', messageSchema);
I import this model into a mocha test suite, where I'm trying to run a test along the lines of:
const now = {Date message was created}
it('check time matches time created', () => {
expect(message.created).to.equal(now);
});
The way I tried to accomplish this was using Sinon's Fake timers functionality.
So my test case looks like this:
describe('creating new message', () => {
let clock;
let message;
let now;
before(() => {
clock = sinon.useFakeTimers();
clock.tick(100);
message = new Message({
user: 'Test User',
message: 'Test Message',
});
// Time the message was created
now = Date.now();
clock.tick(100);
});
it('check time matches time created', () => {
expect(message.created).to.equal(now);
});
});
I believe that this doesn't work because the Date.now
function which is passed as the default for the Mongoose model is isolated from the Sinon fake timer (the fake timer is in the test file, and the model is imported from another file).
Thank you again!
Just wrap Date.now
in an anonymous function, just like that:
function() { return Date.now(); }
Or an ES6 version
() => Date.now()
So the Schema would become something like:
const messageSchema = mongoose.Schema({
user: { type: String, required: true },
message: { type: String, required: true },
created: { type: Date, default: () => Date.now() },
});
Because when you do sinon.useFakeTimers()
, what sinon does at the back is to override the global
property Date
.
And calling Date
is the same than calling global.Date
.
When you pass Date.now
to mongoose, you're essentially passing the Node internal method referenced by global.Date
, and mongoose will call this method, without accessing the global.Date
reference anymore.
But, with my solution, we're passing a method that, when called, accesses the reference of global.Date
, which now is stubbed by Sinon.
In order to see this behavior in practice, you can do in Javascript something like:
var nativeDate = Date; // accessing global.Date
Date = { now: () => 1 }; // overrides global.Date reference to a entirely new object
console.log(Date.now()); // now it outputs 1
console.log(nativeDate.now()); // outputs current date, stub doesn't work here, because it's calling the javascript native Date method, and not global.Date anymore
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With