问题
How can I test like:
init.js lama.system module
angular.module('lama.system', [])
.config(['$httpProvider', function($httpProvider) {
// Crossdomain requests not allowed if you want do cors request see filter.php
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}])
.run(['$rootScope', '$state', '$log', 'Global',function ($rootScope, $state, $log, Global) {
$rootScope.$state = $state;
$rootScope.$log = $log;
$rootScope.global = Global;
}]);
controllers.js lama.system module
angular.module('lama.system')
.controller('SystemController', ['$scope',
function($scope) {
$scope.test =[];
}
]);
services.js lama.system module
angular.module('lama.system')
.factory('Menus', ['$http', function($http) {
return {
query : function(menus){
return $http.get('/api/v1/user/menus', {
params: {
'menus[]': menus
}
});
}
};
}]);
system.js router
//Setting up route
angular.module('lama.system')
.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home', {
url: '/',
templateUrl: 'system/views/home.html',
controller:'SystemController'
});
}
]);
init.js lama module
angular.module('lama', ['ui.router','restangular','lama.system','lama.users'])
.run(['$rootScope', 'Menus',function ($rootScope, Menus) {
// Default hard coded menu items for main menu
var menus = [
{
'permission': null,
'title': 'Home',
'link': 'home'
},
{
'permission': 'users',
'title': 'User',
'link': 'user_actions.list'
}
];
$rootScope.menus = [];
function queryMenu(menus) {
Menus.query(menus).then(
function (result) {
$rootScope.menus = result.data;
},
function (reason) {
throw new Error(reason);
}
);
}
// Query server for menus and check permissions
queryMenu(menus);
$rootScope.$on('loggedin', function(event,user) {
console.log('kkk');
queryMenu(menus);
$rootScope.global = {
user: user,
authenticated: user.groups.length,
isAdmin: user.groups.indexOf('Admins')
};
});
}]);
The test
(function() {
describe('Unit test: system module', function () {
describe('SystemController', function () {
// load the controller's module
beforeEach(function() {
module('lama');
module('stateMock');
});
var SystemController,
$rootScope,
$scope,
$httpBackend;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, _$rootScope_, _$httpBackend_) {
$rootScope = _$rootScope_;
$scope = _$rootScope_.$new();
$httpBackend = _$httpBackend_;
SystemController = $controller('SystemController', {
$scope: $scope
});
$httpBackend.when('GET', '/api/v1/user/menus').respond(200,{});
}));
it('should attach a list of awesomeThings to the scope', function () {
expect($scope.test.length).toBe(0);
});
it('should expose some global scope', function() {
expect($rootScope.global).toBeTruthy();
});
});
});
}());
that give me :(
grunt test
Running "karma:unit" (karma) task
INFO [karma]: Karma v0.12.21 server started at http://localhost:9876/
INFO [launcher]: Starting browser PhantomJS
WARN [watcher]: Pattern "/home/whisher/public_html/public/users/tests/unit/**/*.js" does not match any file.
INFO [PhantomJS 1.9.7 (Linux)]: Connected on socket zK1SplAjTHe4x5sAM9ew with id 16331650
WARN [web-server]: 404: /api/v1/user/menus?menus%5B%5D=%7B%22permission%22:null,%22title%22:%22Home%22,%22link%22:%22home%22%7D&menus%5B%5D=%7B%22permission%22:%22users%22,%22title%22:%22User%22,%22link%22:%22user_actions.list%22%7D
WARN [web-server]: 404: /system/views/home.html
ERROR: 'Error: [object Object]
at http://localhost:9876/base/public/init.js?c7a481724bcf81e4810141349c93d0f698a18904:34
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:100
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:100
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:101
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:112
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:109
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:112
at h (http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:72)
at x (http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:77)
at http://localhost:9876/base/public/bower_components/angular/angular.min.js?4b4cffd940f7a29168096212664973432d1d7449:78'
PhantomJS 1.9.7 (Linux): Executed 2 of 2 SUCCESS (0.039 secs / 0.065 secs)
Done, without errors.
NB
I'm using ui-router
回答1:
I've taken a look at your source code. The primary offending item is:
angular.element(document).ready(function() {
angular.bootstrap(document, ['lama']);
});
By including your manual bootstrap in the files that karma imports, your app is un-necessarily being bootstrapped within the karma test environment. So, instead, move your lama
module into a separate file, and omit init.js
from your files to be included by karma.
There are also a couple of other design concerns that are causing excessive test setup. When testing SystemController
there is no need to include anything but the lama.system
module (as this is what the controller belongs to). Your test setup for this controller can be as simple as:
var $scope, $rootScope;
beforeEach(module('system.lama'));
beforeEach(inject(function($controller, _$rootScope_) {
$rootScope = _$rootScope_;
$scope = $rootScope.$new();
$controller('SystemController', {$scope: $scope});
}));
You will note that in isolating the lama.system
module as above, you will get an error that $state
cannot be injected (not found). This is because your module definition should instead be:
angular.module('lama.system', ['ui.router'])
(A module should not require the presence of another module for its own dependencies, else it can never function in isolation).
One final observation on your mocking for the lama
module run
block. Strictly speaking you should stub the service query
method entirely and not just part of its implementation, else your test is completely isolated. Therefore, instead, it would be better to do the following:
beforeEach(module(function($provide) {
$provide.decorator('Menus', function($delegate, $q) {
// overwrite the query method
$delegate.query = function() {
return $q.when([{id: 1, name: 'Bob'}]);
};
return $delegate;
});
}));
This way, you don't need to worry about using $httpBackend
at all.
来源:https://stackoverflow.com/questions/25363969/karma-angularjs-how-to-test-run-block-with-an-asynchronous-service