Simulate time in a unit test

Amir Elemam
3 min readApr 7, 2021

Sometimes we need to implement functions that need to be executed by cronjobs. It’s a good practice to unit test those functions, so let’s learn how to simulate a given time in a unit test!

What we’re going to do

Verify if function is executed at 15:20:00 (UTC) of 30th July 2019 (epoch 1564500000).

How we’re going to do it

First we’re going to create a function that checks if it’s 15:20:00 (UTC) of 30th July 2019. Then we’re going to create two unit tests:

  • Simulate that’s 15:20:00 (UTC) of 30th July 2019
  • Simulate that’s NOT 15:20:00 (UTC) of 30th July 2019

Step-by-step

  1. Create a new node project
$ mkdir time-unit-test # Create new folder
$ cd time-unit-test # Enter folder created
$ npm init -y # Create new empty node.js project

2. Install lolex, moment and jest

$ npm i -S moment
$ npm I -D lolex jest

3. Create a folder named src

$ mkdir src

4. Inside the folder src, create the checkTime.js file and the function to be executed:

// checkTime.js
const moment = require("moment");
const checkTime = () => {
const epochJuly30th2019at15h20m00s = 1564500000000;
const currentTimestampInMilisseconds = moment().valueOf();
return currentTimestampInMilisseconds === epochJuly30th2019at15h20m00s;};module.exports = checkTime;

5. Create a folder named __tests__

$ mkdir __tests__

6. Inside the __tests__ folder, create the test file named checkTime.test.js then import lolex, moment and checkTime.js

// checkTIme.test.js
const lolex = require('lolex');
const moment = require('moment');
const checkTime = require('../checkTime');
Folder structure

7. Add a describe block and a beforeAll block to console the current epoch inside the test file

// checkTIme.test.js
const lolex = require('lolex');
const moment = require('moment');
const checkTime = require('../checkTime');describe('simulateTimeWIthLolex: checkTime', () => {
beforeAll(() => {
console.log('Current epoch in milisseconds', moment().valueOf());
});
})

8. Below the beforeAll block, paste the first unit test

// checkTIme.test.js
it('should return true when it is time to do foo', async () => {
const epochJuly30th2019at15h20m00s = 1564500000000;
const clock = lolex.install({ now: epochJuly30th2019at15h20m00s, });
const isTimeToDoFoo = await checkTime();

clock.uninstall();
expect(isTimeToDoFoo).toBe(true);
});
  • First we define the epoch we want to simulate
  • Set current time to the epoch
  • Call the function to check the time
  • Reset the current time
  • Check if the time was equal to the epoch

9. Paste the second test below the first one

// checkTIme.test.js
it('should return false when it is not time to do foo', async () => {
const epochJuly30th2019at15h20m01s = 1564500001000;
const clock = lolex.install({ now: epochJuly30th2019at15h20m01s, });
const isTimeToDoFoo = await checkTime();

clock.uninstall();
expect(isTimeToDoFoo).toBe(false);
});

This test is very similar to the previous one, but here we set the current time to a different one than what the checkTime function expects, the result should be “false”

Final checkTime.test.js file:

// checkTime.test.js
const lolex = require('lolex');
const moment = require('moment');
const checkTime = require('../checkTime');describe('simulateTimeWIthLolex: checkTime', () => {
beforeAll(() => {
console.log('Current epoch in milisseconds', moment().valueOf());
});
it('should return true when it is time to do foo', async () => {
const epochJuly30th2019at15h20m00s = 1564500000000;
const clock = lolex.install({ now: epochJuly30th2019at15h20m00s, });
const isTimeToDoFoo = await checkTime();
clock.uninstall();
expect(isTimeToDoFoo).toBe(true);
});
it('should return false when it is not time to do foo', async () => {
const epochJuly30th2019at15h20m01s = 1564500001000;
const clock = lolex.install({ now: epochJuly30th2019at15h20m01s, });
const isTimeToDoFoo = await checkTime();
clock.uninstall();
expect(isTimeToDoFoo).toBe(false);
});
})

That’s it! You learned how to simulate time in unit tests.

You can check the full repo here.

Update (July/2023): lolex has been renamed to @sinonjs/fake-timers

--

--