Проблемы с тестированием $http.get при возврате данных json с помощью Jasmine и AngularJs

Я уже целый день пытаюсь понять, как проверить результат запроса $http.GET, который возвращает данные из файла .json. Я надеюсь, что кто-то из вас сможет здесь чем-то помочь. Практически приложение работает отлично и возвращает правильный JSON, который я ожидал.

У меня есть контроллер с именем «ProgramController» и служба; «ДатаСервис».

Контроллер:

function ProgramController(DataService) {
    var vm = this;
    vm.timeline = {};

    activate();

    ////////////////
    function activate() {
        DataService.getTimelineData().then(function (data) {
            console.log(data);
        });
    }
}

Сервис:

function DataService($http) {
    var service = {
        getTimelineData: getTimelineData
    };

    return service;

    ///////////////
    function getTimelineData() {
        return $http.get('data/program.json').then(function (httpResult) {
            return httpResult.data;
        });
    }
}

Тесты для проверки ответа контроллера и службы;

describe('Program', function () {

var controller, scope, dataserviceMock, httpBackend;

beforeEach(module('mymodule'));

beforeEach(inject(function ($rootScope, $controller, $injector, $q, $httpBackend, $http) {
    scope = $rootScope.$new();
    httpBackend = $httpBackend;
    
    dataserviceMock = {
        getTimelineData: function () {
            return $http.get('data/program.json').then(function (httpResult) {
                return httpResult.data;
            });
        }
    };

    controller = $controller('ProgramController', { 'DataService': dataserviceMock });
}));

describe('when initializing the controller', function () {
    it('object timeline should be something', function () {
        httpBackend.whenGET('data/program.json').respond(mockedTimelineData);
        httpBackend.flush();
        expect(controller.timeline).toEqual(mockedTimelineData);
    });
});

});

Тест терпит неудачу, когда я пробую это. Хотя свойство «controller.timeline» определено как «{}» в контроллере. Спецификация даже не доходит до этого момента. Она не работает на .flush() httpBackend.

Результат в браузере показывает следующую ошибку:

Ошибка: Неожиданный запрос: GET js/app/program/program.template.html

Больше запросов не ожидается

Который ссылается на шаблон, который принадлежит ProgramController, определенному в определении $stateProvider.

У кого-нибудь из вас есть идея, что я делаю неправильно здесь? Я действительно понятия не имею. Я уже сделал кое-что с $q.defer и обещаю решить в тестах, но я действительно не могу понять это...


person Lars Meijdam    schedule 02.06.2016    source источник


Ответы (2)


@myself.. и @Xnake

В конце концов удалось это исправить!! Окончательно! Я наткнулся на эту статью; http://gonehybrid.com/how-to-write-automated-tests-for-your-ionic-app-part-2/, где внизу у писателя также есть те же проблемы, что и у меня... Отключение кэширования шаблонов было моим рабочее решение!

// disable template caching
beforeEach(module(function($provide, $urlRouterProvider) {  
    $provide.value('$ionicTemplateCache', function(){} );
    $urlRouterProvider.deferIntercept();
}));

Другие решения также написаны здесь; https://github.com/angular-ui/ui-router/issues/212#issuecomment-69974072

person Lars Meijdam    schedule 08.06.2016

Какое значение вы указали для mockedTimelineData? Проблема в том, что ваш getTimelineData() вызывает фактическую конечную точку, поэтому выдает ошибку запроса. Вы должны издеваться над возвращаемыми данными, когда они пытаются вызвать «data/program.json», например:

dataserviceMock = {
        getTimelineData: function () {
            return $http.get('data/program.json').then(function (httpResult) {
                return [{'id':'1'},{'id':'2'}];
            });
        }
    };

Таким образом, когда вызывается DataService.getTimelineData(), он фактически вызывает предоставленный вами макет.

Обновлять:

Вы можете указать возвращаемое значение фиктивных данных, как в моем исходном сообщении, или указать исходный код, который я предоставил в рабочем примере: http://plnkr.co/edit/rrBfJOdq9igy3UeMlK21?p=preview.

Также я заметил, что в вашем контроллере вы никогда не устанавливаете vm.timeline в обработчике ответов, а вместо этого console.log(data);

person Xnake    schedule 03.06.2016
comment
Хорошо хорошо спасибо! попробую это! mockedTimelineData похож на то, что вы описали в «return [{'id':'1'},{'id':'2'}];'... просто некоторые простые данные json. - person Lars Meijdam; 03.06.2016
comment
хм... тем не менее, когда я делаю httpBackend.flush(), он запрашивает 'js/app/program/program.template.html' :( но еще одно дополнение... не должно ' httpBackend.whenGET('data/program.json ').respond(mockedTimelineData);' достаточно, чтобы имитировать результат в HTTP-запросе? - person Lars Meijdam; 03.06.2016
comment
при выходе из .flush.. «тогда» в контроллере › Dataservice.getTimelineData() вообще не срабатывает.. Ожидание также терпит неудачу, потому что оно проверяет {} toBe {data: data} - person Lars Meijdam; 03.06.2016
comment
Спасибо чувак! Хотя я действительно верю, что ваша реализация работает, я все равно получаю тот же ответ «GET js/app/program/program.template.html», когда вызывается httpbackend.flush() или scope.$apply(). что делать из-за того, что я пытаюсь реализовать это с помощью Ionic, а не простого приложения Angular? - person Lars Meijdam; 06.06.2016