我遇到以下情况的问题:
我有一个Controller进行服务调用,以获取不同的可用语言和问候语。 我想测试这个控制器,我已根据以下网站和文章编写的测试:
Angular unit-test controllers - mocking service inside controller
http://jasmine.github.io/2.2/introduction.html
和当然AngularJs文件
但我觉得我做错了一些事情或者过度测试。
在我写的那些中,前3个传球,但第4个传球(在我眼中是最重要的传球)失败。
有人可以如此友好地帮助我或指出我正确的方向。 似乎我读过的每篇文章都说明了测试的内容和方法。
控制器
angular.module('app')
.controller('MainCtrl', function ($scope, LanguagesService) {
$scope.languages = LanguagesService.getAll();
});
服务
angular.module('app')
.factory('LanguagesService', function () {
var lang = {};
lang.greetings = [
'Welkom bij,',
'Bienvenu chez'
];
lang.languages = [
{
name: 'Nederlands',
code: 'nl'
},
{
name: 'Français',
code: 'fr'
}
];
return {
getAll: function () {
return lang;
}
};
});
我对控制器的单元测试
describe('Controller: MainCtrl', function () {
// load the controller's module
beforeEach(module('app'));
var MainCtrl,
scope,
LanguagesService;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, _LanguagesService_) {
scope = $rootScope.$new();
LanguagesService = _LanguagesService_;
MainCtrl = $controller('MainCtrl', {
$scope: scope,
'LanguagesService': LanguagesService
});
/*
* Spy on service
*/
spyOn(LanguagesService, 'getAll');
}));
/*
* Test 1: Is this test overkill ? As the tests wont run if the service is not injected
*/
it('should get an instance of LanguagesService', function() {
expect(LanguagesService).toBeDefined();
});
it('should attach languages to the scope', function() {
expect(scope.languages).not.toBe(null);
});
it('should have the same amount of languages as greetings', function() {
expect(scope.languages.languages.length).toBe(scope.languages.greetings.length);
});
/*
* Test 4: This test fails
*/
it('should have called LanguagesService method getAll', function() {
expect(LanguagesService.getAll).toHaveBeenCalled();
});
});
答案 0 :(得分:3)
describe('Controller: MainCtrl', function () {
// load the controller's module
beforeEach(module('app'));
var MainCtrl,
scope,
LanguagesService;
var createController;
var spy;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope, _LanguagesService_) {
scope = $rootScope.$new();
LanguagesService = _LanguagesService_;
MainCtrl = $controller('MainCtrl', {
$scope: scope,
'LanguagesService': LanguagesService
});
createController = function () {
return $controller('MainCtrl', {
'$scope': scope,
'LanguagesService': LanguagesService
});
};
/*
* Spy on service
*/
spy = spyOn(LanguagesService, 'getAll');
}));
/*
* Test 1: Is this test overkill ? As the tests wont run if the service is not injected
*/
it('should get an instance of LanguagesService', function () {
expect(LanguagesService).toBeDefined();
});
it('should attach languages to the scope', function () {
expect(scope.languages).not.toBe(null);
});
it('should have the same amount of languages as greetings', function () {
expect(scope.languages.languages.length).toBe(scope.languages.greetings.length);
});
/*
* Test 4: This test fails
*/
it('should have called LanguagesService method getAll', function () {
createController();
expect(spy).toHaveBeenCalled();
});
});
答案 1 :(得分:1)
为了将来参考,这就是我解决问题的方法:
我放弃的第一个测试,看起来真的有点过分了。
我放弃了第3次测试,因为它测试服务的输出而不是控制器的行为,我把这个测试移到我的服务单元测试中。
我设法通过在我的测试中模拟服务来完成第四次测试工作:
'use strict';
describe('controller: MainCtrl', function() {
var ctrl, LanguagesService, $scope;
beforeEach(module('fitApp'));
beforeEach(inject(function($rootScope, $controller) {
LanguagesService = {
getAll: function() {}
};
spyOn(LanguagesService, 'getAll').and.returnValue('Foo');
$scope = $rootScope.$new();
ctrl = $controller('MainCtrl', {$scope: $scope , LanguagesService: LanguagesService });
}));
it('should call LanguagesService.getAll() once', function() {
expect(LanguagesService.getAll).toHaveBeenCalled();
expect(LanguagesService.getAll.calls.count()).toEqual(1);
});
it('should attach languages to the scope', function() {
expect($scope.languages).toEqual('Foo');
});
});
两个测试都通过并测试控制器的行为。
我希望有人可以向我确认这是正确的选择