11

アンダースコアのデバウンスを使用するサービスにメソッドがあります。

そのメソッド内には、別のサービスのメソッドへの呼び出しがあります。別のサービスが呼び出されることをテストしようとしています。

デバウンスされたメソッドをテストしようとすると、さまざまなサービスのメソッドが呼び出されることはなく、ジャスミンは次のように失敗します。

「スパイ aMethod が呼び出されることが予想されます。」

私はそれが呼び出されているという事実を知っています(クロムのコンソールにログを記録します)、期待がすでに失敗した後に呼び出されました。

したがって...(できれば)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 Testing の神々は私を見捨てたのですか?

* stackoverflow で実際にボーナス ポイントを付与する方法がわかりませんが、可能であれば付与します。

4

3 に答える 3

15

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();
  });
});
于 2015-12-28T22:50:56.970 に答える
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(最近のバージョンの Lodashdebounce では提供されます)、非同期テストが利用可能な最良のオプションです。

于 2015-12-29T02:32:12.193 に答える