如何测试控制器的$ scope对象?
我能够获得附加到它的实际数据吗?
我的测试设置如下所示,但myScope
正在说undefined
。
'use strict';
describe('myApp.view1 module', function() {
var $httpBackend, $rootScope, createController, jsonHandler;
beforeEach(module('myApp.view1'));
describe('view1 controller', function(){
beforeEach(inject(function($rootScope, $controller, $injector) {
// Set up the mock http service responses
$httpBackend = $injector.get('$httpBackend');
// backend definition common for all tests
$httpBackend.when('GET', 'view1/quizzes.json')
.respond({data: '[XXX,XXX,XXX]'});
// Get hold of a scope (i.e. the root scope)
$rootScope = $injector.get('$rootScope');
// The $controller service is used to create instances of controllers
var $controller = $injector.get('$controller');
var myScope = $rootScope.$new()
createController = function() {
return $controller('View1Ctrl', {'$scope' : myScope });
};
var controller = createController();
}));
it('should get the json files', function(){
$httpBackend.expectGET('/view1/quizzes.json');
});
it('should get the json files', function(){
expect(myScope).toBe("words");
});
});
});
控制器:
myApp.controller('View1Ctrl', [
'$scope',
'$http',
function($scope, $http) {
$http.get('view1/quizzes.json')
.then(function(res){
$scope.quizzes = res.data.quizzes
})
.then(function(){
$http.get('view1/questions.json')
.then(function(res){
$scope.questions = res.data.questions
})
.then(function(){
$scope.quiz = [ [], [], [], [], [] ]
_($scope.questions).forEach(function(qu){
_($scope.quizzes).forEach(function(quiz){
if (_.includes($scope.quizzes[(quiz.id - 1)].question_ids, qu.id)){
$scope.quiz[(quiz.id - 1)].push(qu)
}
})
})
})
.then(function(){
// console.log($scope.quiz)
})
});
}
]);
答案 0 :(得分:1)
行。首先让我们开始清理一下这个烂摊子。您不需要使用$ injector来访问服务,因为它们可以使用inject注入。
您也不希望对整个模块进行单一测试。您的测试应该只测试控制器。我将向您展示一个测试与后端的第一次交互的示例。
describe('view1 controller', function() {
// declare the variables that need to be used in all tests
// the $scope contains the data and functions we want to test
var $scope;
// the $httpBackend service allows mocking the http... backend
var $httpBackend;
// the $controller service allows instantiating our controller
var $controller;
// load the module containing the component I want to test
beforeEach(module('myApp.view1'));
// prepare the tests. Use inject to access the services we need.
// To avoid a name clash with the variables defined above, we can
// enclose the actual service names into underscores
beforeEach(inject(function($rootScope, _$httpBackend_, _$controller_) {
// initialize our variables
$httpBackend = _$httpBackend_;
$controller = _$controller_;
// create a scope and initialize our $scope variable with it
$scope = $rootScope.$new();
}));
// we need to be able to instantiate our controller in our tests. Let's
// define a function that does that
function createController() {
// we initialize the controller with the scope we have created sooner
// so, the scope the controller receives as argument is our scope
// the controller will populate the scope, and we can test it has
// populated it correctly
$controller('View1Ctrl', { $scope: $scope });
}
// now let's write a simple test. The controller, when instantiated,
// should use $http to load view1/quizzes.json, and, once it gets
// the response, it should populate $scope.quizzes with the quizzes
// attribute of the JSON received as response
it('should populate the quizzes from the backend', function() {
// we first need to tell our fake backend: you should receive a
// request, and when you do, you should return this response
var data = {
quizzes: ['hello world']
};
$httpBackend.expectGET('view1/quizzes.json').respond(data);
// now we will create our controller. The controller should send
// a http request to get the quizzes. If it indeed does correctly,
// the fake backend will return the above data **when we tell it to
// do it**.
createController();
// Now, the controller has sent the request. But it hasn't received
// the response yet. Let's send the response.
$httpBackend.flush();
// now, the controller should have received the response, and should
// thus have extracted the quizzes from it and populated
// $scope.quizzes with them
expect($scope.quizzes).toEqual(data.quizzes);
});
});