【问题标题】:Testing a debounced function in AngularJS with Jasmine never calls the function使用 Jasmine 在 AngularJS 中测试去抖函数从不调用该函数
【发布时间】:2016-04-02 19:03:53
【问题描述】:

我在使用下划线去抖动的服务中有一个方法。

该方法内部是对不同服务上的方法的调用。我正在尝试测试是否调用了不同的服务。

在我尝试测试去抖动方法时,从未调用不同服务的方法,并且 jasmine 失败并显示:

“预期的间谍 aMethod 已被调用。”

我知道它被调用(它在 chrome 中记录到控制台),它只是在期望已经失败之后才被调用。

所以...(最好)不添加 Sinon 或其他依赖项并且使用
给予解决方案的奖励积分*不必将 _.debounce 变成 $timeout...

怎么做?

angular.module('derp', [])
.service('herp', function(){ 
   return {
     aMethod: function(){ 
       console.log('called!'); 
       return 'blown'; 
     }
   }; 
 })
 .service('Whoa', ['herp', function(herp){
   function Whoa(){
     var that = this;
     this.mindStatus = 'meh';
     this.getMind = _.debounce(function(){
       that.mindStatus = herp.aMethod();
     }, 300);
   }
   return Whoa;
 }]);

测试:

describe('Whoa', function(){
  var $injector, whoa, herp;

  beforeEach(function(){
    module('derp');
    inject(function(_$injector_){
      var Whoa;
      $injector = _$injector_;
      Whoa = $injector.get('Whoa');
      herp = $injector.get('herp');
      whoa = new Whoa();
    });
  });

  beforeEach(function(){
    spyOn(herp, 'aMethod').andCallThrough();
  });

  it('has a method getMind, that calls herp.aMethod', function(){
    whoa.getMind();
    expect(herp.aMethod).toHaveBeenCalled();
  });
});

为什么 AngularJS 测试之神抛弃了我?

* 我不知道如何在 stackoverflow 上给出实际的奖励积分,但如果可能的话,我会的。

【问题讨论】:

    标签: javascript angularjs jasmine underscore.js debouncing


    【解决方案1】:

    我的去抖函数接受了参数,所以我像这样嘲笑_.debounce

    spyOn(_, 'debounce').and.callFake(function(cb) {return cb});

    (对@Wawy 的回答稍作修改)

    【讨论】:

      【解决方案2】:

      你只需要模拟 lodash debounce 方法:

      describe('Whoa', function(){
        var $injector, whoa, herp;
      
        beforeEach(function(){
          module('derp');
          spyOn(_, 'debounce').and.callFake(function(cb) { return function() { cb(); } });
          inject(function(_$injector_){
            var Whoa;
            $injector = _$injector_;
            Whoa = $injector.get('Whoa');
            herp = $injector.get('herp');
            whoa = new Whoa();
          });
        });
      
        beforeEach(function(){
          spyOn(herp, 'aMethod').andCallThrough();
        });
      
        it('has a method getMind, that calls herp.aMethod', function(){
          whoa.getMind();
          expect(herp.aMethod).toHaveBeenCalled();
        });
      });
      

      【讨论】:

      • 不。还是行不通。在我们的两种情况下,都调用了 herp.aMethod,但在期望之前都没有调用。
      • 我希望我现在能像承诺的那样拥有柴。 “最终”会解决这个问题。
      • 在callfake里面的匿名函数里面放一个断点,然后检查堆栈看看它是从哪里调用的。
      • 模拟函数真的被调用了吗?
      • @AndrewLuhring 我已经编辑了我的答案。我现在意识到为什么它不起作用,在注入器实例化您的服务之后间谍正在完成,所以为时已晚。现在,它应该可以工作了。
      【解决方案3】:

      Angular $timeout 在测试中具有优势,因为它在测试中被模拟为同步。当使用第三方异步工具时,不会有这个优势。一般来说,异步规范看起来像这样:

      var maxDelay = 500;
      
        ...
        it('has a method getMind, that calls herp.aMethod', function (done){
          whoa.getMind();
          setTimeout(function () {
            expect(herp.aMethod).toHaveBeenCalled();
            done();
          }, maxDelay);
        });
      

      由于 Underscore debounce 不提供 flush 功能(而最新版本的 Lodash debounce does),异步测试是最好的选择。

      【讨论】:

        猜你喜欢
        • 2017-05-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-28
        • 1970-01-01
        • 1970-01-01
        • 2021-04-26
        • 1970-01-01
        相关资源
        最近更新 更多