16

非同期メソッドを持つサービスを単体テストしようとしていますが、うまくいきません。

angularjs の $q サポートを使用して、promise を実装しようとしました。

どんな助けでも大歓迎です。

http://jsfiddle.net/9pBze/37/

angular.module('myapp', ['myservice']);

angular.module('myservice', []).factory('myservice', function($q) {
  var ls = {};

  ls.DoIt = function() {
    var deferred = $q.defer();

    setTimeout(function(){
        deferred.resolve(5);
    },3000);

    return deferred.promise;
  }

  return ls;

});

describe('services', function () {

    beforeEach(module('myservice'));

    it("should equal 2",  inject(function(myservice) {
        myservice.DoIt().then(function(returned) {
            expect(returned).toEqual(2);
        });        
    }));
});
4

2 に答える 2

30

まず第一に、setTimeoutはモックするのが難しいため、テストするのが特に難しいです。幸いなことに、AngularJS にはそれを囲むラッパー ( $timeout) があり、同じ役割を果たしますが、簡単にモックできます。

  ls.DoIt = function() {
    var deferred = $q.defer();

    $timeout(function(){
        deferred.resolve(5);
    },3000);

    return deferred.promise;
  }

に提供されているモックを$timeout使用すると、( を使用して) 経過時間を簡単にシミュレートできます$timeout.flush()。これは、非同期イベントが完了するのを実際に待つことなく、テストを高速に実行できることを意味します (製品コードはまだ非同期 API を使用していることに注意してください!)。

変更されたテストは次のようになります。

it("should equal 5",  inject(function(myservice, $timeout) {

    var valueToVerify;
    myservice.DoIt().then(function(returned) {
      valueToVerify = returned;  
    });  
    $timeout.flush();        
    expect(valueToVerify).toEqual(5);
}));

最後に、動作中の jsFiddle: http://jsfiddle.net/v9L9G/1/

于 2013-03-18T13:23:52.167 に答える
4

Angular 自体とは関係ありませんが、Jasmine async testsとは関係ありません。

setTimeoutAngular を使用する必要がある場合$timeout。また、 setTimeout/$timeout の実行を細かく制御したい場合は、モック化された Clockを使用してください。

于 2013-03-18T13:31:17.193 に答える