0

У меня есть контроллер, который вызывает службу, которая является оболочкой для Ресурса. Например:Контроллер тестирования, который зависит от службы, основанной на ресурсе

app.factory("Service", ["$resource", function ($resource) { 
      return $resource("/api/Service/get"); 
     }]); 

Возвращаемое значение метода услуги присваивается переменной внутри контроллера. Обычно переменная имеет тип Resource и содержит promise. Когда обещание будет разрешено, переменная заполняется всеми значениями, возвращаемыми из бэкэнд. Я отслеживаю , затем на обещании, чтобы изменить модель, полученную от бэкэнд. Как так:

this.model = Service.get(); 
    this.model.$promise.then(function(data) { 
     // do something with data 
    }); 

мне нужно проверить значение результирующего модели переменных в моем контроллере. Единственным способом, который я нашел для этого, является использование $ httpBackend с реальной реализацией моего Сервиса. Однако это уродливо, потому что тогда, тестируя мой контроллер, я должен пройти путь запроса "api/Service/get" до httpBackend.when(), чтобы он мог ответить некоторым значением.

Отрывок образуют мой тест:

// call Controller 
$httpBackend.when('GET', '/api/Service/get').respond(someData); 
$httpBackend.flush(); 
expect(scope.model.property).toBe(null); 

Это, кажется, и чувствует себя совершенно неправильно. Весь смысл использования отдельной службы для работы с ресурсом заключается в том, что контроллер не знает ничего о имени метода url и http. И что же мне делать?

Другими словами, я хочу проверить, что then получает вызов и делает то, что мне нужно для этого.

Возможно, я мог бы создать отдельную службу, которая вызывается в then, и делать то, что мне нужно сделать с моделью, но она чувствует себя немного перехитрить, если все, что я хочу сделать, это, например, установить одно поле в null в зависимости от простого условия.

+0

ли эта работа для вас ? – tasseKATT

ответ

0

Вы правы, вам не нужно использовать $httpBackend, если вы не используете $http в контролере, который вы тестируете.

Как вы писали, диспетчеру не нужно ничего знать о реализации Service. Контроллер знает, что Service имеет метод get, который возвращает объект с свойством $promise, который является обещанием.

Что вы хотите сделать, это использовать поддельную реализацию Service в вашем тесте. Существует несколько способов сделать это с помощью mocks, spies, stubs и т. Д., В зависимости от вашего варианта использования и используемой вами рамки (-и) тестирования.

Один из способов заключаются в создании фальшивой реализации, как это:

var Service = { 
    get: function() { 

    deferred = $q.defer(); 

    return { 
     $promise: deferred.promise 
    }; 
    } 
}; 

Вы хотите, чтобы иметь возможность получить доступ к deferred из тестов, так что вы можете либо resolve или reject обещания основаны на том, что вы хотите проверить ,

Полная установка:

var $rootScope, 
    scope, 
    createController, 
    $q, 
    deferred; 

var Service = { 
    get: function() { 

    deferred = $q.defer(); 

    return { 
     $promise: deferred.promise 
    }; 
    } 
}; 

beforeEach(function() { 

    module('App'); 

    inject(function(_$rootScope_, $controller, _$q_) { 

    $rootScope = _$rootScope_; 

    scope = $rootScope.$new(); 

    createController = function() { 
     $controller('MyController', { 
     $scope: scope, 
     Service: Service 
     }); 
    }; 

    $q = _$q_; 
    }); 
}); 

реализация контроллер:

app.controller('MyController', function($scope, Service) { 

    $scope.property = false; 

    $scope.model = Service.get(); 

    $scope.model.$promise.then(function(data) { 

    if (data) { 
     $scope.property = true; 
    } 
    }); 
}); 

Вы можете следить за фальшивую реализацию утверждать, что она называется правильно.

Пример с Жасмином:

spyOn(Service, 'get').and.callThrough(); 

Вам нужно and.callThrough() или вызов будет прерван и не будут использоваться ваши фальшивые реализации.

Теперь у вас есть полный контроль, создавая вручную контроллер, разрешение обещание и запуск дайджест цикла и может тестировать различные состояния:

it('Should work', function() { 

    spyOn(Service, 'get').and.callThrough(); 

    expect(Service.get).not.toHaveBeenCalled(); 

    createController(); 

    expect(Service.get).toHaveBeenCalled(); 

    expect(scope.property).toBeFalsy(); 

    deferred.resolve('some data'); 
    $rootScope.$digest(); 

    expect(scope.property).toBeTruthy(); 
}); 

Демо:http://plnkr.co/edit/th2pLWdVa8AZWOyecWOF?p=preview

Смежные вопросы