我正在尝试在Jasmine中编写一个简单的测试来测试SearchCtrl。但是我不确定如何构建单元测试,因为这是我第一次使用它。这是我到目前为止所做的:
services.js :中的
function CategoryService($http) {
this.getCategoryList = function () {
return $http({
method: 'GET',
url: server + '/api/category/',
});
}
}
示例输出:
[
{
"id": "1551742a-5963-4d40-9abb-af7a6fb4ec5d",
"category": "Coach"
}
]
controller.js :中的
function SearchCtrl($scope, CategoryService) {
CategoryService.getCategoryList().then(function(dataResponse) {
$scope.categories = dataResponse.data;
});
}
在 search.controller.tests.js :
中describe('SearchCtrl', function() {
var $controller, scope, categoryServiceMock;
// TODO: Load the app module
beforeEach(module('app.controllers'));
beforeEach(module('app.services'));
// TODO: Instantiate the controller and mocks
beforeEach(inject(function($controller, categoryServiceMock) {
scope = $rootScope.$new();
// mock categoryService
categoryServiceMock = {
login: jasmine.createSpy('category spy')
};
// instantiate SearchCtrl
controller = $controller('SearchCtrl', {
$scope: scope,
'CategoryService': categoryServiceMock
})
}));
describe('#searchList', function() {
// TODO: Call getCategoryList() on the controller
it('should call getCategoryList on categoryService', function() {
expect(categoryServiceMock.getCategoryList).toHaveBeenCalledWith('Coach');
});
describe('once the search is executed', function() {
it('if successful, return a list of categories', function() {
// TODO: Mock response from CategoryService
expect(categoryServiceMock.getCategoryList).toHaveBeenCalledWith('Coach');
});
});
});
});
目前返回错误:
Error: [$injector:unpr] Unknown provider: categoryServiceMockProvider <- categoryServiceMock
我该如何解决?此外,我是否以正确的方式构建了单元测试?
更新25/09
我将测试更改为以下内容:
describe('SearchCtrl', function() {
var scope;
var CategoryServiceMock;
var SearchCtrl;
// Load the app module
beforeEach(module('dingocv.controllers', ['dingocv.services']));
// Define CategoryServiceMock
beforeEach(function() {
CategoryServiceMock = {
getCategoryList: function() {}
};
});
// Inject required services and instantiate the controller
beforeEach(inject(function($rootScope, $controller) {
scope = $rootScope.$new();
SearchCtrl = $controller('SearchCtrl', {
$scope: scope,
CategoryService: CategoryServiceMock
});
}));
// Tests
describe('#searchList', function() {
it('should call registerBook Parse Service method', function () {
spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough();
scope.getCategoryList();
})
});
});
我现在收到此错误:
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 0 of 1 SUCC
PhantomJS 2.1.1 (Windows 8 0.0.0) SearchCtrl #searchList should call registerBook Parse Service method FAILED
forEach@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:13691:24
loadModules@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17878:12
createInjector@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17800:30
workFn@D:/myapp-mobile/www/lib/angular-mocks/angular-mocks.js:3074:60
loaded@http://localhost:9876/context.js:151:17
D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17918:53
TypeError: undefined is not a constructor (evaluating 'spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough()') in unit-tests/search.controller.tests.js (line 30)
unit-tests/search.controller.tests.js:30:67
loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FPhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.04 secs / 0.021 secs)
25 09 2016 09:48:38.940:INFO [watcher]: Changed file "D:/myapp-mobile/www/tests/unit-tests/search.controller.tests.js".
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 0 of 1 SUCCPhantomJS 2.1.1 (Windows 8 0.0.0) SearchCtrl #searchList should call registerBook Parse Service method FAILED
forEach@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:13691:24
loadModules@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17878:12
createInjector@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17800:30
workFn@D:/myapp-mobile/www/lib/angular-mocks/angular-mocks.js:3074:60
loaded@http://localhost:9876/context.js:151:17
D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17918:53
TypeError: undefined is not a constructor (evaluating 'spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough()') in unit-tests/search.controller.tests.js (line 30)
unit-tests/search.controller.tests.js:30:67
loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FPhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.035 secs / 0.007 secs)
25 09 2016 09:48:42.307:INFO [watcher]: Changed file "D:/myapp-mobile/www/tests/unit-tests/search.controller.tests.js".
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 0 of 1 SUCCPhantomJS 2.1.1 (Windows 8 0.0.0) SearchCtrl #searchList should call registerBook Parse Service method FAILED
forEach@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:13691:24
loadModules@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17878:12
createInjector@D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17800:30
workFn@D:/myapp-mobile/www/lib/angular-mocks/angular-mocks.js:3074:60
loaded@http://localhost:9876/context.js:151:17
D:/myapp-mobile/www/lib/ionic/js/ionic.bundle.js:17918:53
TypeError: undefined is not a constructor (evaluating 'spyOn(CategoryServiceMock, 'getCategoryList').andCallThrough()') in unit-tests/search.controller.tests.js (line 30)
unit-tests/search.controller.tests.js:30:67
loaded@http://localhost:9876/context.js:151:17
PhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FPhantomJS 2.1.1 (Windows 8 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.069 secs / 0.008 secs)
答案 0 :(得分:2)
您只是简单地使用所有这些注射使测试变得复杂。这是一个简单的工作示例:
服务模块
angular.module('dingocv.services', [])
.service('CategoryService', ['$http', function CategoryService($http) {
this.getCategoryList = function () {
//Wasn't sure what server was here. So created a variable here. Feel free to change this.
var server = 'https://www.example.com';
return $http({
method: 'GET',
url: server + '/api/category/',
});
}
}]);
控制器模块
angular.module('dingocv.controllers', ['dingocv.services'])
.controller('SearchCtrl', ['$scope', 'CategoryService', function SearchCtrl($scope, CategoryService) {
CategoryService.getCategoryList().then(function(dataResponse) {
$scope.categories = dataResponse.data;
});
}]);
<强>测试强>
describe('SearchCtrl', function() {
var response;
response = {
status: 200,
data: [{
"id": "1551742a-5963-4d40-9abb-af7a6fb4ec5d",
"category": "Coach"
}]
};
//Injecting the modules that would then be used in the tests
beforeEach(module('dingocv.services'));
beforeEach(module('dingocv.controllers'));
beforeEach(inject(function($controller, $rootScope, _CategoryService_) {
$scope = $rootScope.$new();
CategoryService = _CategoryService_;
//Creating a spy for this method so that it doesn't call the original Service method.
spyOn(CategoryService, 'getCategoryList').and.callFake(function(){
return{
then: function(successCallback){
successCallback(response);
}
}
});
SearchCtrl = $controller('SearchCtrl', {
$scope: $scope
});
}));
describe('Initialization', function() {
it('should initialize the controller\'s scope with categories', function(){
expect(CategoryService.getCategoryList).toHaveBeenCalled();
expect($scope.categories).toBeDefined();
expect($scope.categories.length).toEqual(1);
expect($scope.categories[0].id).toEqual(response.data[0].id);
expect($scope.categories[0].category).toEqual(response.data[0].category);
});
});
});
希望这有帮助。