使用Jasmine模拟多个方法调用

时间:2017-02-22 00:05:37

标签: javascript unit-testing jasmine

我试图用JavaScript编写测试,我测试的方法进行2次方法调用(model.expandChildren()和view.update();)

// inside 'app' / 'RV.graph'
var expandChildren = function(){
    return model.expandChildren().then(function(r) {
      view.update(r);
    });
};

我尝试使用Jasmine规范将测试编写为spyOn视图和模型函数,但看起来你在给定的测试中只能有1个间谍。我似乎错过了一些大的东西,应该有一种方法来模拟使用间谍的多个方法调用,因为我的函数需要进行这两个调用。

我希望我的规范能够以下面的方式运行,但它目前只通过第一次测试(第一个间谍按预期运行),第二次测试失败,因为Jasmine正在尝试运行实际的功能,而不是间谍功能:

var model = GRAPH.model;
var view = GRAPH.view;
var app = RV.graph;

describe('#expandChildren', function() {

    beforeEach(function() {
        // first spy, all good
        spyOn(model, 'expandChildren').and.callFake(function() {
          return new Promise(function(resolve) {
            resolve(testResponse);
          });
        });
        // second spy doesn't work because Jasmine only allows 1
        spyOn(view, 'update');
        app.expandChildren();
    });

    // passing test
    it('calls model.expandChildren', function() {
        expect(model.expandChildren).toHaveBeenCalled();
    });

    // failing test that runs the REAL view.update method
    it('calls view.update', function() {
        expect(view.update).toHaveBeenCalled();
    });
});

有没有办法用Jasmine做到这一点?

1 个答案:

答案 0 :(得分:1)

请记住,您正在使用异步调用。第一个调用是同步的,所以它被记录,但第二个调用仅在稍后发生。让事情发生时给自己一些控制权。我通常使用这样的模式:

describe('#expandChildren', function() {
    var resolver;

    it('calls model.expandChildren', function(done) {
        spyOn(model, 'expandChildren').and.callFake(function() {
          return new Promise(function(resolve) {
            resolver = resolve;
          });
        });
        spyOn(view, 'update');

        app.expandChildren();

        expect(model.expandChildren).toHaveBeenCalled();
        expect(view.update).not.toHaveBeenCalled();

        resolver();
        done();

        expect(view.update).toHaveBeenCalled();
    });
});

这样,只有在解析了promise并且调用done()后才会运行规范。