javascriptnode.jssinon

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?


Solution

  • @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.