【问题标题】:Mocking out multiple method calls using Jasmine使用 Jasmine 模拟多个方法调用
【发布时间】:2017-07-11 20:14:05
【问题描述】:

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

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

我尝试使用 Jasmine 规范编写测试以监视视图和模型功能,但似乎在给定测试中您只能有 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 做到这一点?

【问题讨论】:

    标签: javascript unit-testing jasmine


    【解决方案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() 被调用后运行。

    【讨论】:

    • 解决绝对是这里的另一个问题,但即使使用done(),我的第二次测试仍然失败。我可能会误解,但我的印象是每个描述块只能使用一个间谍,即使您在测试套件中有多个间谍。
    • 您可以创建的间谍数量没有限制。无论如何,在创建时同步解决一个承诺可能还为时过早。我从未尝试过这种模式,但总是手动解决。这样,您还可以测试您的异步代码 is 仅稍后执行。请参阅编辑后的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多