如何为 setInterval() 函数编写测试用例

How to write a test case for a setInterval() function

我有一个计时器并假设当计数器计数到 3 时将执行特定功能。

var a_interval_function = function(){
    var counter = 1;
    var interval = setInterval(function(){
        if(counter === 5){
            clearInterval(interval);
        }

        // run the function when the counter is 3
        if(counter === 3){
            a_function_should_be_runned();
        }   

        counter++;
    }, 500);

    return interval;
}

但是,我不知道如何建立一个有效的测试用例来测试计数器以及函数执行的时间。有谁知道该怎么做?类似于以下内容:

// and some test case like this
it('a timer test', function(done){
    var interval = a_interval_function();
    expect(a_function_should_be_runned.state).to.equal({
        name: 'runned',
        counter: 3,
        time: 300,
    });
});

谢谢。

检查代码/函数是否被执行的最简单方法就是发出警报或 console.log,这样您就可以直观地确认正在发生的事情。您还可以 console.log 间隔中的计数器,这样您就可以看到计数器在上升。

屋子里的语法纳粹....

[编辑]

var a_interval_function = function(){
    var counter = 1;
    var interval = setInterval(function(){
        if(counter === 5){
            clearInterval(interval);
        }

        // run the function when the counter is 3
        if(counter === 3 && testFunction()){
            a_function_should_be_runned();
        }   

        counter++;
    }, 500);

    return interval;
}

function testFunction(){
     if(KeyboardNinja == 'awesome'){
         return true;
     } else {
         return false;
     }


}

你的测试永远不会失败:P

这是我天真的方法:

it('a timer test', function(done){
    var interval = a_interval_function();
    setTimeout(function () {
        expect(a_function_should_be_runned.state).to.equal({
            name: 'runned',
            counter: 3,
            time: 300,
        });
        done();
    }, 3.5 * 500);
});

你在这里所做的基本上是等待 1.75s 并期望 a_function_should_be_runned 函数已在超时时执行。然后你调用 expect 函数来检查你的断言。最后你打电话给 done()。请注意,done() 是在 setTimeout 回调函数内部调用的。如果您不调用 done(),您的测试就会超时。

也许你可以使用 sinon.useFakeTimers()

例如:

var sinon  = require('sinon');
var expect = require('chai').expect;

var a_function_should_be_runned = sinon.spy();

var a_interval_function = function(){
  var counter = 1;
  var interval = setInterval(function(){
    if(counter === 5){
      clearInterval(interval);
    }

    // run the function when the counter is 3
    if(counter === 3){
      a_function_should_be_runned();
    }   

    counter++;
  }, 500);

  return interval;
}

describe('timer tests', function() {

  before(function() {
    this.clock = sinon.useFakeTimers();
  });

  after(function() {
    this.clock.restore();
  });

  it('a timer test', function() {
    var interval = a_interval_function();

    // At time 0, we don't expect the function to have been called.
    expect(a_function_should_be_runned.called).to.be.false;

    // Advance clock 500ms.
    this.clock.tick(500);
    expect(a_function_should_be_runned.called).to.be.false;

    // Advance clock again (1s since start)
    this.clock.tick(500);
    expect(a_function_should_be_runned.called).to.be.false;

    // Advance clock again (1.5s since start). This should
    // trigger the call to `a_function_should_be_runned`.
    this.clock.tick(500);
    expect(a_function_should_be_runned.called).to.be.true;
  });
});