Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Progressing time in child process in mocha test

I am using node-cron to schedule a task to be executed once a day, and I want to test this in mocha.

I am using child_process.spawn to run the script, and I need to progress the internal clock of the created child. This is what i have so far:

it.only('Should run the script every 24 hours and trigger an event',function(done){
    var clock = sinon.useFakeTimers(),
           path = process.cwd() + '/cronjob/',
           env = Object.create(process.env);

    env.NODE_ENV = 'test';
    var cronjob = child.spawn('node', ['index.js'], {
            cwd: path,
            env: env
     });
    cronjob.stdout.on('data',function(data){
          console.log(data);
          if (data.toString().trim() === 'Script ran successfully'){
               cronjob.kill('SIGINT');
               done();
          }
     });
     cronjob.stderr.on('data',function(data){
          done(new Error(data.toString()));
      });
      clock.tick(24*60*60*1000);
}

This only progresses time in the mocha test instance not in the index.js. Is there any way i can pass the sinon timer to the child process?

like image 414
Stelios Savva Avatar asked Jun 05 '26 16:06

Stelios Savva


1 Answers

I'm not sure if this will be at all useful, but I've done something similar using Node's vm. Here's a VERY simplified version of what I've done in the past.

Sample index.js:

setTimeout(function() {
  console.log('ok');
}, 24*60*60*1000);

Sample index.spec.js

var sinon = require('sinon');
var vm = require('vm');
var fs = require('fs');

describe('sample', function() {
  it('Should detect if script runs 24 hours later',function(){
    var clock = sinon.useFakeTimers();
    var script = fs.readFileSync(require.resolve('../index.js'));
    sinon.stub(console, 'log');

    var result = vm.runInThisContext(script);
    clock.tick(24*60*60*1000);

    sinon.assert.calledOnce(console.log);
    sinon.assert.calledWith(console.log, 'ok');

    console.log.restore();
  });
});

Sample output:

  sample
    ✓ Should run the script every 24 hours and trigger an event


  1 passing (19ms)

In the above sample code I accomplish the following:

  1. setup Sinon's fake timers
  2. stub console.log() so I can make assertions later
  3. execute the sample index.js in vm using the current context, but isolated from the local scope (index.js calls console.log() 24 hours later)
  4. time travel 24 hours using Sinon's fake timers
  5. make assertions on calls to console.log()
  6. restore console.log() (so Mocha reporters don't get cranky)

Since I don't know what's going on in your index.js it's hard to say if a solution like the one I've outlined above could be helpful, but I hope it is.

like image 77
JME Avatar answered Jun 08 '26 09:06

JME