How do I stub new Date() using sinon?

JavascriptTestingSinonStub

Javascript Problem Overview


I want to verify that various date fields were updated properly but I don't want to mess around with predicting when new Date() was called. How do I stub out the Date constructor?

import sinon = require('sinon');
import should = require('should');

describe('tests', () => {
  var sandbox;
  var now = new Date();

  beforeEach(() => {
    sandbox = sinon.sandbox.create();
  });

  afterEach(() => {
    sandbox.restore();
  });

  var now = new Date();

  it('sets create_date', done => {
    sandbox.stub(Date).returns(now); // does not work

    Widget.create((err, widget) => {
      should.not.exist(err);
      should.exist(widget);
      widget.create_date.should.eql(now);

      done();
    });
  });
});

In case it is relevant, these tests are running in a node app and we use TypeScript.

Javascript Solutions


Solution 1 - Javascript

I suspect you want the useFakeTimers function:

var now = new Date();
var clock = sinon.useFakeTimers(now.getTime());
//assertions
clock.restore();

This is plain JS. A working TypeScript/JavaScript example:

var now = new Date();

beforeEach(() => {
    sandbox = sinon.sandbox.create();
    clock = sinon.useFakeTimers(now.getTime());
});

afterEach(() => {
    sandbox.restore();
    clock.restore();
});

Solution 2 - Javascript

sinon.useFakeTimers() was breaking some of my tests for some reason, I had to stub Date.now()

sinon.stub(Date, 'now').returns(now);

In that case in the code instead of const now = new Date(); you can do

const now = new Date(Date.now());

Or consider option of using moment library for date related stuff. Stubbing moment is easy.

Solution 3 - Javascript

I found this question when i was looking to solution how to mock Date constructor ONLY. I wanted to use same date on every test but to avoid mocking setTimeout. Sinon is using [lolex][1] internally Mine solution is to provide object as parameter to sinon:

let clock;

before(async function () {
    clock = sinon.useFakeTimers({
        now: new Date(2019, 1, 1, 0, 0),
        shouldAdvanceTime: true,
        advanceTimeDelta: 20
    });
})

after(function () {
    clock.restore();
})

Other possible parameters you can find in [lolex][1] API [1]: https://github.com/sinonjs/lolex#api-reference

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMrHenView Question on Stackoverflow
Solution 1 - JavascriptAlex BookerView Answer on Stackoverflow
Solution 2 - JavascriptrealplayView Answer on Stackoverflow
Solution 3 - JavascriptAnatoli KlamerView Answer on Stackoverflow