Модульное тестирование службы angular.js (сервер node.js) в контроллере
Я новичок в модульном тестировании на стороне клиента. Мое приложение использует express.js, angularjs-ui-router и node.js. В настоящее время я начинаю писать тестовые примеры для приложения. Я использую Карма, Мокко, Чай, Синон для юнит-тестирования.
Мой конфиг роутера выглядит так:
$stateProvider
.state('drive', {
url: '/drive',
templateUrl: 'drive.jade',
controller: 'driveCtrl',
});
контроллер:
angular.module('mApp').controller('driveCtrl', ['$scope', 'driveService',
function($scope, driveService) {
var driveInfo = driveService.get({}, function() {});
driveInfo.$promise.then(function(rs) {
var drivers = [];
//Logical operation
$scope.drivers = drivers;
});
}]);
Фабрика Ресурс:
mApp.factory('driveService', ['$resource', function($resource) {
return $resource('/drive/id/:id/', {id:'@id'});
}]);
DriveService - это фабрика, которая использует ресурсы angular.js $. Я пробовал различные варианты, но ничего не работает (используя $httpbackend, $q). Можете ли вы помочь мне написать способ тестирования контроллера, издеваясь над DriveService.
Вот мой код модульного теста:
var expect = require('chai').expect;
var sinon = require('sinon');
describe('Drive Service initialisation', function() {
var scope, controller, state, $q, mockDriveService, driveServiceResponse = [{name:'james', type: 'heavy'}], queryDeferred;
beforeEach(angular.mock.module('mApp'));
angular.mock.module(function($provide){
$provide.value('driveService', mockDriveService);
});
describe(' drive service called', function() {
beforeEach(inject(function($controller, $rootScope, $state, _$q_, driveService) {
$q = _$q_;
scope = $rootScope.$new();
mockDriveService = {
get:function(){
queryDeferred = $q.defer();
queryDeferred.resolve(driveServiceResponse);
return {$promise: queryDeferred.promise};
}
};
controller = $controller('driveCtrl', { $scope: scope, driveService:driveService});
sinon.stub(mockDriveService, 'get');
scope.$apply();
}));
it('expect filter to be empty', function () {
expect(scope.drivers).to.not.be.empty;
});
});
});
Ошибка, которую я получаю:
Error: Unexpected request: GET /driveService/id
No more request expected
at $httpBackend (node_modules/angular-mocks/angular-mocks.js:1210:9)
at sendReq (public/javascripts/lib/angular/angular.js:10333:9)
at serverRequest (public/javascripts/lib/angular/angular.js:10045:16)
at processQueue (public/javascripts/lib/angular/angular.js:14567:28)
at public/javascripts/lib/angular/angular.js:14583:27
at Scope.$eval (public/javascripts/lib/angular/angular.js:15846:28)
at Scope.$digest (public/javascripts/lib/angular/angular.js:15657:31)
at Scope.$apply (public/javascripts/lib/angular/angular.js:15951:24)
at Context.<anonymous> (C:/Users/por/AppData/Local/Temp/b0475694b46e0d60262621ad126ce46c.browserify:63:9)
at Object.invoke (public/javascripts/lib/angular/angular.js:4450:17)
Error: Declaration Location
at window.inject.angular.mock.inject (node_modules/angular-mocks/angular-mocks.js:2375:25)
1 ответ
Вы определяете фиктивную службу, но по-прежнему предоставляете немодированную driveService
для контроллера (это уже было сделано по умолчанию).
Дело в том, что driveService.get
заглушается после того, как был создан экземпляр контроллера и вызван метод, не помогает в этом случае.
Это должно быть что-то вроде
mockDriveService = {
get: sinon.stub().returns({$promise: $q.resolve(driveServiceResponse)})
};
controller = $controller('driveCtrl', { $scope: scope, driveService:mockDriveService});
scope.$apply();
Приложение должно иметь дружественный к тестированию дизайн для эффективного тестирования. Учитывая, что маршрутизатор загружен в модуль верхнего уровня и его конфигурация также определена там, модули приложения, которые должны быть проверены, должны быть определены в дочерних модулях, чтобы их можно было тестировать изолированно.
Приложение может быть переработано как
angular.module('mApp', ['ui.router', 'mApp.drive']);
...
angular.module('mApp.drive', [])
.controller('driveCtrl', ...)
.factory('driveService', ...);
И его единицы могут быть проверены как
beforeEach(angular.mock.module('mApp.drive'));
...