使用 sinon FakeTimers 测试节点调度

问题描述 投票:0回答:3

我想测试

scheduleJob
包中的
node-schedule
。有了 sinon
useFakeTimers()
我可以跳过时间。不幸的是,我的调度程序似乎并不“相信”假时间。当我将调度程序设置为 1 分钟时,它运行得很好,所以我知道它可以运行。我还尝试在通话前一分钟设置假时间,也不起作用。

诗乃:

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

我预定的工作:

 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));

有人有什么想法吗?

javascript node.js sinon
3个回答
1
投票

@MPasman

您的测试是什么样的?节点调度作者用 sinon 测试他们的代码,所以我不明白为什么这会成为一个问题。

参见示例

我能够使用 jasmine 的 fakeAsync 在 Angular 6 中测试我的工作,如下所示:

  
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);
      }));

我正在测试的服务中的实际功能:

  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'));
    });
  }

基本策略是:

1)监视 cronJob 在计划时应调用的函数

2)取消所有以前的作业(如果有)(您也可以在 afterEach 中执行此操作,它在每个单元测试之后运行)。 Node-schedule 还提供了一个名为

scheduledJobs
的函数,它返回一个包含所有已调度函数的对象。你可以循环它并取消它们)

3) 将

cronTime
设置为每秒运行一次,以便于测试

4)将时钟滴答一秒多一点(在我的例子中,我做了 3 秒多一点)

5)取消作业以停止它(否则它将继续运行并且您的测试将超时)。

6)期望你的函数被调用 x 次

希望这对您有帮助。


0
投票

基本上

sinon.useFakeTimers()
方法用内置的同步方法替换了 setInterval 和 setTimeout 异步方法,您可以使用
clock.tick()

进行控制

clock.tick(time)
方法调用替换的同步方法,并且基本上按指定的
time
转发时间。

另一方面,

node-schedule
是一个
cron-like
作业调度程序,因此它不使用setInterval和setTimeout

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

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

希望这能让它更清楚一点


0
投票

@nsikimic 响应的最后一部分是错误的,

node-schedule
确实通过库使用了
setTimeout
long-timeout

https://github.com/node-schedule/node-schedule/blob/master/lib/Inspiration.js#L3 https://github.com/tellnes/long-timeout/blob/master/index.js#L41

© www.soinside.com 2019 - 2024. All rights reserved.