Angular $q.when не е разрешен в модулния тест на Karma

Използвам $q.when за обгръщане на други lib обещания. Работи като чар, но когато се опитам да го стартирам в Karma, обещанието не успява да се разреши (done() никога не се изпълнява), дори ако стартирах $digest и дори след таймаут. Ето примерен код:

describe('PouchDB', function () {
var $q, $rootScope;

beforeEach(inject(function (_$rootScope_, _$q_) {
    $rootScope = _$rootScope_;
    $q = _$q_;
}));

it("should run", function (done) {

    function getPromise() {
        var deferred = Q.defer();

        deferred.resolve(1);

        return deferred.promise;
    }

    $q.when(getPromise())
        .then(function () {
            done();   // this never runs
        });

    $rootScope.$digest();
});

Защо? Каква е причината за това? Наистина не мога да го получа.

Актуализация (заобиколно решение)

Не разбирам защо $q.when не е разрешено в Karma - има нещо с функцията nextTick, но не мога да отстраня проблема. Вместо това се отказах от $q.when и написах проста функция, която преобразува PouchDB (или всяка друга като Q) в $q:

.factory('$utils', function ($q, $rootScope) {
  return {
    to$q: function (promise) {
      var deferred = $q.defer();

      promise.then(function (result) {
        deferred.resolve(result);
        $rootScope.$digest();
      });

      promise.catch(function (error) {
        deferred.reject(error);
        $rootScope.$digest();
      });

      return deferred.promise;
    }
  }
})

person Yoorek    schedule 13.06.2014    source източник
comment
Защо използвате Q и $q заедно? Може би Karma (или библиотеката AngularMocks, която използва) очаква обещания, генерирани от $q.defer() вместо Q.defer()   -  person Sunil D.    schedule 15.06.2014
comment
Използвам PouchDB, който има свои собствени обещания, така че трябва да ги обвия с $q. Използвах Q в примера само за да опростя нещата - резултатът обаче е същият: $q.when не е разрешен в Karma, когато обгръща външни обещания, което между другото е основната цел на $q.when   -  person Yoorek    schedule 15.06.2014


Отговори (2)


От Как да разреша $q.all обещания в Jasmine unit тестове? изглежда, че трикът е:

$rootScope.$apply();

Току-що имах същия проблем и това работи за мен; обещанията са изпълнени при извършване на това обаждане.

person Andrew Magee    schedule 16.11.2014

Коригирах променливи и инжектирах имена на зависимости за това, за да поддържам нещата ясни, докато писането на тестове продължава. Ако done() е функция във вашия (контролер? директива? услуга/фабрика?), тогава тя трябва да бъде извикана, когато тестът се изпълнява, без да се опитвате да я прехвърлите като зависимост. В идеалния случай done() трябва да бъде шпиониран, но без да знаем откъде идва, е невъзможно да ви покажем как да настроите шпионската функция.

Единствената друга липсваща подробност е, че нямате expect() в този пакет от тестове. Без него нямам начин да разбера какво очаквате да бъде заявено.

describe('PouchDB', function () {
    var scope, db, q, rootScope;

    beforeEach(
        inject(
            function(_$rootScope_, _$q_){
                rootScope = _$rootScope_;
                scope = rootScope.$new();
                q = _$q_;
            }
        )
    );

    it("should run", function(){

        //spy should be constructed here

        function getPromise() {
            var deferred = q.defer();

            deferred.resolve(1);

            return deferred.promise;
        }

        q.when(getPromise)
            .then(function () {
                done();
            });

        scope.$digest();

        //assertion should be here

    });
});
person MBielski    schedule 13.06.2014
comment
Моята подготовка е проста и не създавам нов обхват (редактирах въпроса) Опитах с $timeout и flush... нищо не се промени - person Yoorek; 14.06.2014
comment
Опитайте да създадете новия обхват и да премахнете времето за изчакване. - person MBielski; 14.06.2014
comment
Не разбирам защо би променило нещо - не използвам $scope изрично, така или иначе не работи. - person Yoorek; 15.06.2014
comment
Човече, done() е функция на Jasmine за асинхронно тестване в Karma. Assert не е важно, ако кодът не може да бъде достигнат. - person Yoorek; 15.06.2014
comment
Никога не съм имал причина да използвам done() и съм склонен да забравя за това. - person MBielski; 16.06.2014