Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在AngularJS中测试控制器服务调用_Angularjs_Unit Testing_Service_Controller_Karma Runner - Fatal编程技术网

在AngularJS中测试控制器服务调用

在AngularJS中测试控制器服务调用,angularjs,unit-testing,service,controller,karma-runner,Angularjs,Unit Testing,Service,Controller,Karma Runner,我对以下情况有问题: 我有一个控制器,它执行服务调用以获取不同的可用语言及其问候语。 我想测试这个控制器,我基于我在以下网站和文章中编写的测试: 当然还有AngularJs文档 但是我有一种感觉,我做了一些错误的事情,或者做了一些过度的测试 在我写的那些文章中,前3篇通过了,但第4篇(在我看来是最重要的一篇)失败了 有没有人能帮我一把或给我指出正确的方向。 似乎我读到的每一篇文章在测试内容和方法上都有所不同 控制器 angular.module('app') .controller('Ma

我对以下情况有问题:

我有一个控制器,它执行服务调用以获取不同的可用语言及其问候语。 我想测试这个控制器,我基于我在以下网站和文章中编写的测试:

当然还有AngularJs文档

但是我有一种感觉,我做了一些错误的事情,或者做了一些过度的测试

在我写的那些文章中,前3篇通过了,但第4篇(在我看来是最重要的一篇)失败了

有没有人能帮我一把或给我指出正确的方向。 似乎我读到的每一篇文章在测试内容和方法上都有所不同

控制器

angular.module('app')
.controller('MainCtrl', function ($scope, LanguagesService) {
    $scope.languages = LanguagesService.getAll();
});
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();
});

});
服务

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;

    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();
    });

});
控制器的我的单元测试

angular.module('app')
.controller('MainCtrl', function ($scope, LanguagesService) {
    $scope.languages = LanguagesService.getAll();
});
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();
});

});

以下是我解决问题的方法,以供将来参考:

我放弃的第一次测试,看起来真是太过分了

我也放弃了第三个测试,因为它测试服务的输出,而不是控制器的行为,所以我将这个测试移到了我的服务单元测试中

通过在测试中模拟服务,我成功地进行了第四次测试:

'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');
  });

});
这两个测试都通过并测试控制器的行为


我希望有人能向我确认这是一个正确的选择

供将来参考,以下是我解决问题的方法:

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;

    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();
    });

});
我放弃的第一次测试,看起来真是太过分了

我也放弃了第三个测试,因为它测试服务的输出,而不是控制器的行为,所以我将这个测试移到了我的服务单元测试中

通过在测试中模拟服务,我成功地进行了第四次测试:

'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');
  });

});
这两个测试都通过并测试控制器的行为


我希望有人能向我确认这是正确的选择

您的测试有什么问题?你看到错误了吗?为了使用
调用
测试对象需要是间谍。我已经在beforeach(spyOn(LanguagesService,'getAll');)中放置了间谍,还是应该将其放置在另一个位置才能工作?我现在明白了。不,那应该行。jasmine给出的测试失败的原因是什么?PhantomJS 1.9.8(Linux)Controller:MainCtrl应该调用LanguageService方法getAll FAILED,而spy getAll应该被调用。at/test/spec/controllers/main.js:36您的测试有什么问题?你看到错误了吗?为了使用
调用
测试对象需要是间谍。我已经在beforeach(spyOn(LanguagesService,'getAll');)中放置了间谍,还是应该将其放置在另一个位置才能工作?我现在明白了。不,那应该行。jasmine给出的测试失败的原因是什么?PhantomJS 1.9.8(Linux)Controller:MainCtrl应该调用LanguageService方法getAll FAILED,而spy getAll应该被调用。在/test/spec/controllers/main.js:36中,我在beforeEach方法中定义了一个函数createController,因此如果从测试中调用此方法,它将运行并调用getAll()函数。在beforeEach方法中,我定义了一个函数createController,因此如果从测试中调用此方法,它将运行并调用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;

    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();
    });

});