如何在AngularJS控制器中测试$ scope

时间:2016-07-01 05:58:42

标签: angularjs

如何测试控制器的$ 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)
      })
    });
  }
]);

1 个答案:

答案 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);
  });
});