Угловой тест: Как я могу проверить угловое обещание с ajax в нем?

0

Как я могу проверить угловое обещание с помощью ajax?

Код состоит в том, чтобы вызвать родителя через ajax, а затем вызвать остальную часть своих дочерних элементов через ajax.

Код,

app.controller('MyController', ['$scope', '$http', '$timeout', '$q', function($scope, $http, $timeout, $q) {

    $scope.myParen = function(url) {
        var deferred = $q.defer();

        setTimeout(function() {
        $http({
            method: 'GET',
            url: url
        })
        .success(function(data, status, headers, config) {
            deferred.resolve([data]);
        })
        .error(function(data, status, headers, config) {
            deferred.reject(data);
        });
        }, 1000);

        return deferred.promise;
    }

    $scope.submit = function() {
        $scope.commentCollection = '';

        var promise = $scope.myParen('https://example.com/parents/1');

        promise.then(function(success) {
            var list = success;

            $http({
                method: 'GET',
                url: 'https://example.com/parents/1/children'
            })
            .success(function(data, status, headers, config) {
                $scope.commentCollection = list.concat(data);
            })
            .error(function(data, status, headers, config) {
                $scope.error = data;
            });
        }, function(error) {
            $scope.error = error;
        });
    };

}]);

Контрольная работа,

describe('MyController Test', function() {

    beforeEach(module('RepoApp'));

    var controller, $scope, $http, $httpBackend, $q;
    var deferred;

    beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend, $q) {

        $scope = $rootScope.$new();

        deferred = $q.defer();

        // Create the controller.
        controller = $controller;
        controller("MyController", {$scope, $http, $httpBackend, $q});
    }));

    it('should demonstrate using when (200 status)', inject(function($rootScope, $http, $httpBackend, $q) {

        var $scope = {};

        /* Code Under Test */
        $scope.myParen = function(url) {
            ...
        }

        $scope.submit = function() {
            ...
        };
        /* End */

        $scope.submit();

        deferred.promise.then(function (value) {

            $httpBackend.whenGET('https://example.com/parents/1/children', undefined, {})
            .respond(function(){ return [200,{foo: 'bar'}]});

            expect(value).toBe(4);
        });
        deferred.resolve(4);
        $rootScope.$apply();

        expect($scope.commentCollection).toEqual({foo: 'bar'});
    }));
});

Неудачный результат,

Expected '' to equal { foo: 'bar' }.

Есть идеи?

Редактировать:

....
deferred.resolve(4);
$rootScope.$apply();

$timeout.flush();
expect($scope.commentCollection).toEqual({foo: 'bar'});
  • 0
    Почему вы вставили $timeout в свой контроллер, а затем не использовали его? Замените setTimeout на $timeout .
  • 0
    В тестах вы можете использовать $timeout.flush() чтобы синхронно очистить очередь отложенных функций.
Показать ещё 2 комментария
Теги:
karma-jasmine
promise

2 ответа

2
Лучший ответ

1) переключатель setTimeout на $timeout в контроллере

2) замените все $httpBackend в функции beforeEach

3) использовать функции .flush()

describe('MyController Test', function() {

beforeEach(module('app'));

var controller, $scope, $http, httpBackend, $q;
var deferred;

beforeEach(inject(function ($rootScope, $controller, $http, $httpBackend, $q) {

    $httpBackend
        .whenGET('https://example.com/parents/1', undefined, {})
        .respond(function(){ return [200, {parents: []}]});

    $httpBackend
        .whenGET('https://example.com/parents/1/children', undefined, {})
        .respond(function(){ return [200, {foo: 'bar'}]});

    $scope = $rootScope.$new();

    deferred = $q.defer();

    // Create the controller.
    controller = $controller;
    controller("MyController", {$scope: $scope, $http: $http, $httpBackend: $httpBackend, $q: $q});
}));

it('should demonstrate using when (200 status)', inject(function($httpBackend, $timeout) {

    // var $scope = {}; // don't write it, becouse you rewrite a scope which defined at beforeEach function
    $scope.submit();   
    //$httpBackend.flush(); // wait when backend return parents
    $timeout.flush(); // wait timeout in $scope.myParen 
    $httpBackend.flush(); // wait when backend return children

    expect($scope.commentCollection[0]).toEqual({parents: []});
    expect($scope.commentCollection[1]).toEqual({foo: 'bar'});
}));

});

  • 0
    Благодарю. но почему вы не помещаете реальный код контроллера в тест под /* Code Under Test */ ? это неправильно?
  • 0
    Кроме того, я проверил ваш код, но я получаю эту ошибку Error: No pending request to flush !
Показать ещё 8 комментариев
1

$scope.myParen функцию $scope.myParen чтобы использовать $timeout вместо setTimeout.

$scope.myParen = function(url) {

    var promise = $http({
        method: 'GET',
        url: url
    })
    .then (function(response) {
        var data = response.data;
        return $timeout(function(){return data;}, 1000);
    })
    .catch(function(response) {
        var data = response.data;
        return 
            ($timeout(angular.noop, 1000)
            ).then (function () {
                 throw data;
            });
    });

    return promise;
}

Затем в тестах вы можете использовать $timeout.flush() для синхронного сброса очереди отложенных функций.

Уведомление об изъятии

$ Http legacy обещает, что методы success и error устарели. Используйте стандарт, then метод.

- Ссылка на API-интерфейс AngularJS $ HTTP - уведомление об отказе

  • 0
    Благодарю. но почему у него нет var deferred = $q.defer(); в этом?
  • 3
    $ http уже дает обещание, нет необходимости добавлять $ q.defer для него
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню