如何监视在Jasmine中调用其他函数的函数?

时间:2016-05-19 04:40:38

标签: javascript testing asynchronous jasmine

我遇到了问题:

var async = require('async');

function a() {
  async.series([b,c], function(err) {
    console.log('Done');
  });
};
function b(next) {
  next();
};
function c(next) {
  next();
};

var methods = {
  a: a,
  b: b,
  c: c
};

我正在尝试编写一个类似的测试:

spyOn(methods.a);
methods.a();
expect(methods.b).toHaveBeenCalled();
expect(methods.c).toHaveBeenCalled();

然而,b和c都没有注册为已被调用。任何想法如何正确测试这种行为?

2 个答案:

答案 0 :(得分:0)

如果你在函数或方法上使用间谍,那么Jasmine会看看这个函数来检查它。 Jasmine Spy下的被调用函数默认不执行其代码。

spyOn(methods, "a");
methods.a();
expect(methods.a).toHaveBeenCalled();

在您的情况下,您需要检查异步代码执行。我们可以使用done函数:

来完成
it("should support async execution", function(done) {
    var MAX_ASYNC_DELAY = 2000;
    spyOn(methods, "b");
    spyOn(methods, "с");
    methods.a();
    setTimeout(function(){
        expect(methods.b).toHaveBeenCalled();
        expect(methods.c).toHaveBeenCalled();
        done();
    }, MAX_ASYNC_DELAY );
});

如果在methods.a()中您将使用下一个:

,它将起作用
function a() {
     async.series([methods.b, methods.c], function(err) {
          console.log('Done');
     });
}

如果无法进行此类调整,则应重写以下测试用例:

it("should support async execution", function(done) {
    var MAX_ASYNC_DELAY = 2000;
    spyOn(window, "b");
    spyOn(window, "с");
    methods.a();
    setTimeout(function(){
        expect(b).toHaveBeenCalled();
        expect(c).toHaveBeenCalled();
        done();
    }, MAX_ASYNC_DELAY );
});

Owen Ayres建议不要在测试用例中使用setTimeout。但是如果你使用的是Jasmine,这在你的情况下是不可能的。因为jasmine.DEFAULT_TIMEOUT_INTERVAL超时等待调用done函数。 例如,您的异步超时几乎是10000毫秒,并将MAX_ASYNC_DELAY设置为11000毫秒。测试用例将被标记为失败,因为jasmine.DEFAULT_TIMEOUT_INTERVAL默认等于5000毫秒。需要使用覆盖此参数:

var originalTimeout;
beforeEach(function() {
    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 12000; // ms to wait for done()
});
it("should support async execution", function(done) {
    var MAX_ASYNC_DELAY = 11000;
    // test case from above
});
afterEach(function() {
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});

如果你使用Jasmine 2.2及以上版本,你可以写:

it("should support async execution", function(done) {
    var MAX_ASYNC_DELAY = 11000;
    // test case from above
}, 12000);

答案 1 :(得分:0)

不惜一切代价避免单位测试setTimeout。以下是如何在可读的“三A测试”中对其进行测试的方法。格式。如果从未进行函数调用,则使用Jasmine的异步done将确保它在失败之前等待一段时间。如果你想为这个测试用例自定义这个,你可以做我在下面的beforeEach中定义的东西(但是在测试本身里面)。

beforeEach(function() {
    // these are not required, including to show you can have if desired
    originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
    jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; // ms to wait for done()
});

it('calls methods b and c when a is called', function (done) {
    var a = spyOn(methods.a);
    var b = spyOn(methods.b);

    methods.a();

    expect(a).toHaveBeenCalled();
    expect(b).toHaveBeenCalled();
    done();
});

afterEach(function() {
    // could be inline of above test if not needed for multiple cases.
    jasmine.DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
});

不要在测试中使用超时。这不是一种干净的测试方式,应该避免,除非绝对必不可少。