Единичное тестирование асинхронной службы в angularjs - программирование
Подтвердить что ты не робот

Единичное тестирование асинхронной службы в angularjs

Я пытаюсь использовать unit test службу с асинхронными методами, но мне не повезло.

Я попытался реализовать с помощью promises с помощью поддержки $q в angularjs.

Любая помощь будет оценена.

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);
        });        
    }));
});
4b9b3361

Ответ 1

Прежде всего, setTimeout особенно сложно тестировать, так как трудно издеваться. К счастью, у AngularJS есть обертка вокруг него ($timeout), которая играет ту же роль, но ее можно легко высмеять:

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

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

    return deferred.promise;
  }

Макет, предоставленный для $timeout, позволяет нам легко имитировать прошедшее время (с $timeout.flush()), что означает, что наши тесты могут выполняться быстро, не дожидаясь завершения асинхронного события (обратите внимание, что производственный код все еще используется async 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/

Ответ 2

Он не связан с Angular сам, а тесты Jasmine async.

Если вам нужно setTimeout использовать Angular $timeout. И если вы хотите иметь прекрасный контроль над выполнением setTimeout/$timeout, используйте mocked Clock.