Угловое обещание не разрешается в жасмин

У меня есть следующий жасминовый тест:

it('should resolve promise', inject(function ($q, $rootScope) {

    function getPromise(){
        var deferred = $q.defer();
        setTimeout(function(){
            deferred.resolve(true);
        }, 1000);
        return deferred.promise;
    }

    var p = getPromise();
    var cb = jasmine.createSpy();

    runs(function(){
        expect(cb).not.toHaveBeenCalled();

        p.then(cb);

        $rootScope.$apply();
    });

    waitsFor(function(){
        return cb.callCount == 1;
    });

    runs(function(){
        expect(cb).toHaveBeenCalled();

        $rootScope.$apply();
    });

}));

Я думал, что $rootScope.$apply должен разрешать все невыполненные промисы, но почему-то в этом тесте этого не происходит.

Как запустить выполнение промисов в таком тесте? пожалуйста помоги!


person Elmer    schedule 01.12.2013    source источник
comment
Какую версию Angular вы используете? В angularJS 1.2 промисы совместимы с A+, и они должны разрешаться без явного вызова для выполнения цикла $digest.   -  person musically_ut    schedule 01.12.2013
comment
Я использую угловой 1.2. Ну, я знаю, что они ДОЛЖНЫ разрешаться в цикле дайджеста. Но это не так. :-(   -  person Elmer    schedule 02.12.2013
comment
Ну, когда я вызываю $apply сразу после разрешения, это работает. Но я думаю, что это все еще странное поведение. Когда я пытаюсь использовать то же решение в своем реальном модульном тесте (представленный здесь только для тестирования поведения $apply), он терпит неудачу. Так что, кажется, у меня все еще есть проблема!   -  person Elmer    schedule 02.12.2013
comment
Работал только $scope.$apply, а не $timeout? Я удалю это из решения, если это не так.   -  person musically_ut    schedule 02.12.2013
comment
Я подготовил plnkr: plnkr.co/mKRgNQYqJkccbPgzPEBe Метод применения работает, а решение с тайм-аутом — нет. что странно   -  person Elmer    schedule 02.12.2013
comment
Это прозвенел звонок. Служба $timeout издевается над ngMock (дох!), и нужно явно вызвать $timeout.flush(): plnkr.co /edit/Bdh78ZiArbO8vau9ByVJ?p=preview   -  person musically_ut    schedule 02.12.2013


Ответы (1)


Я думаю, что в вашем случае $rootScope.$apply() вызывается слишком рано. Это должно работать:

function getPromise(){
    var deferred = $q.defer();
    setTimeout(function(){
        deferred.resolve(true);
        $rootScope.$apply();
    }, 1000);
    return deferred.promise;
}

Обновить

Вы можете внедрить фиктивную службу $timeout и разрешить промис, явно используя $timeout.flush().

it('should resolve promise', inject(function ($q, $timeout, $rootScope) {

    function getPromise(){
        var deferred = $q.defer();
        $timeout(function(){
            deferred.resolve(true);
        }, 1000); 
        return deferred.promise;
    }

    // ...

    $timeout.flush();

    // ...
person musically_ut    schedule 01.12.2013