MPasman
MPasman

Reputation: 13

Test node-schedule with sinon FakeTimers

I want to test my scheduleJob from the node-schedule package. With sinon useFakeTimers() i can skip the time. Unfortunately my scheduler doesn't seem to 'believe' the fake time. When i set the scheduler to 1 minute it works perfectly, so i know that it works. I also tried to set the fake time just a minute before the call, also doesn't work.

Sinon:

let clock = sinon.useFakeTimers(moment().toDate());
                clock.tick(60*60*23);

And my scheduledJob:

 let job_2 = schedule.scheduleJob(new Date(date.toISOString()), function (user) {
        console.log("get's here..");
        if (user.status === 'pending') {
            user.remove(function (error) {
                if (!error) {
                    mid.addEvent({
                        action: 'deleted_user'
                    }, {
                        name: user.name
                    }, function (error) {
                        if (error) {
                            console.log("error: " + error);
                        }
                    });
                }
            });
        }
    }.bind(null, user));

Has anyone any idea?

Upvotes: 0

Views: 3326

Answers (2)

baby.zard
baby.zard

Reputation: 234

@MPasman

What does your test look like? The node-schedule authors test their code with sinon so I don't see why this would be an issue.

see this for examples

I was able to test my job in angular 6 using jasmine's fakeAsync like so:

  
it('should call appropriate functions when cronJob is triggered, bad ass test',
      fakeAsync(() => {
        const channelSpy = spyOn(messengerService, 'createChannels');
        const listenerSpy = spyOn(messengerService, 'createListener');
        const messengerSpy = spyOn(messengerService.messenger,
            'unsubscribeAll');
        // reset your counts
        channelSpy.calls.reset();
        listenerSpy.calls.reset();
        messengerSpy.calls.reset();
        messengerService.cronJob.cancel();
        // run cron job every second
        messengerService.cronJobTime = '* * * * * *';
        messengerService.scheduleMyJsCronJob();
        tick(3150);
        messengerService.cronJob.cancel();
        expect(channelSpy.calls.count()).toEqual(3);
        expect(listenerSpy.calls.count()).toEqual(3);
        expect(messengerSpy.calls.count()).toEqual(3);
      }));

The actual function in the service I am testing:

  scheduleMyJsCronJob(): void {
    this.cronJob = scheduleJob(this.cronJobTime, () => {
      //  logic to unsubscribe at midnight
      this.messenger.unsubscribeAll();
      // create new channels
      this.createChannels(
          this.sessionStorageService.getItem('general-settings'));
      this.createListener(
          this.sessionStorageService.getItem('general-settings'));
    });
  }

The basic strategy is:

1) spy on functions that your cronJob should call when scheduled

2) cancel all previous Jobs if any (you could also do this in an afterEach, which runs after each unit test). Node-schedule also offers a function called scheduledJobs which returns an object with all the functions scheduled. You can loop over it and cancel them all)

3) set the cronTime to run every second for easier testing

4) tick the clock a little over a second (in my case i did a little over 3 seconds)

5) cancel the job to stop it (otherwise it will keep running and your test will timeout).

6) expect your function(s) to be called x amount of times

Hope this helps you.

Upvotes: 1

nsikimic
nsikimic

Reputation: 1

Basically sinon.useFakeTimers() method replaces setInterval and setTimeout asynchronous methods with a built in synchronous methods that you can control using clock.tick()

clock.tick(time) method invokes the replaced synchronous methods and basically forwards the time by time specified.

node-schedule on the other hand is a cron-like job scheduler so it doesn't use setInterval and setTimeout

https://www.npmjs.com/package/node-schedule

https://sinonjs.org/releases/v1.17.6/fake-timers/

Hope this makes it a little more clear

Upvotes: -1

Related Questions