Jasmine测试:$ scopeProvider< - $ scope< - > DetailController

时间:2017-03-12 17:29:21

标签: javascript angularjs jasmine

我是AngularJS的新手。我创建了以下包含模板和关联控制器的组件。

angular.
module('beerDetail').
controller('BeerDetailController',  ['BeerSelection', '$scope', '$rootScope',
  function BeerDetailController(BeerSelection, $scope, $rootScope) {

    let beerSelected = BeerSelection.getBeerSelected();

    $scope.ok = () => { $rootScope.modalInstance.close() };
    $scope.beer = beerSelected;
    $scope.foodPairings = beerSelected.food_pairing.join(", ");

    this.getFormattedIngredients = (ingredients) => {...};

    this.getFormattedMethod = (method) => {...};

    $scope.allIngredients = this.getFormattedIngredients(beerSelected.ingredients);
    $scope.method = this.getFormattedMethod(beerSelected.method);
  }
]).
component('beerDetail', {
  templateUrl: '/components/beer-detail/beer-detail.template.html',
  controller: 'BeerDetailController',
});

我想测试控制器,我创建了以下测试,检查传入范围的啤酒是否是通过调用提供的啤酒:

describe('BeerDetailController', function() {

  beforeEach(module('beerDetail'));

  let ctrl;
  let $controller;
  let scope;
  let rootScope;
  let createController;
  let beerSelection;
  let beerSelected = {
    "id": 192,
    "name": "Punk IPA 2007 - 2010",
  };

  beforeEach(inject(function ($controller, $rootScope) {
    scope = $rootScope.$new();
    createController = function () {
      ctrl = $controller('BeerDetailController',
        {'BeerSelection': beerSelection},
        {'$scope': scope},
        {'$rootScope': rootScope}
      );
      spyOn('BeerSelection', 'getBeerSelected').and.returnValues(beerSelected);
    };
  }));

  it('returns the selected beer', function() {

    createController();
    expect(ctrl).toBeDefined();
    expect(scope.beer).toEqual(beerSelected);
    });
  });

但我确实收到以下错误:

  

错误:[$ injector:unpr]未知提供者:$ scopeProvider< - $ scope< -   BeerDetailController

这让我发疯,有谁知道问题出在哪里?提前谢谢!

3 个答案:

答案 0 :(得分:2)

实例化控制器时,本地提供为单个对象:

//ERRONEOUS
createController = function () {
  ctrl = $controller('BeerDetailController',
    {'BeerSelection': beerSelection},
    {'$scope': scope},
    {'$rootScope': rootScope}
  );

//CORRECT
createController = function () {
  let locals = {
    'BeerSelection': beerSelection,
    '$scope': scope,
    '$rootScope': rootScope
  };
  ctrl = $controller('BeerDetailController', locals);
};

有关详细信息,请参阅AngularJS $controller Service API Reference

答案 1 :(得分:1)

对于

createController = function () {
  ctrl = $controller('BeerDetailController',....

您应该获取组件控制器

//1. inject _$componentController_
//2. var ctrl = _$componentController_('beerDetail', null, bindings);
 it('returns the selected beer', function() {
    expect(ctrl).toBeDefined();
 }); 

请参阅:https://docs.angularjs.org/guide/component#unit-testing-component-controllers

答案 2 :(得分:1)

正如@georgeawg建议的那样,您必须在单个对象中提及$controller方法的第二个参数的所有本地人。但这并不能解决整个问题。

理想情况下,你应该只是嘲笑注射剂,就像你必须做BeerSelection一样。这意味着你必须模拟getBeerSelected方法,因为它已被控制器直接使用。

let locals = {
    'BeerSelection': beerSelection,
    '$scope': scope,
    '$rootScope': rootScope
};

然后你必须正确地模仿BeerSelection服务,如下所示

let beerSelected = {
    "id": 192,
    "name": "Punk IPA 2007 - 2010",
};

//BeerSelection service mocking
let beerSelection = {
    //mocked getBeerSelected method
    getBeerSelected: function() {
      return beerSelected;
    }
};

Plunker Demo