角度控制器测试:检查依赖注入是否正确

时间:2017-06-02 12:49:49

标签: javascript angularjs testing frontend

有时,通常在重构Controller或者工厂时,我最终会通过我的Controller测试,但是当我的应用启动并运行时,它会在某些时候崩溃,因为我忘了添加/更新依赖注入。

我的意思是,我要说我有以下控制器,我以前有一个oldDependency,但由于重构,我使用的是newDependency。我使用新更改更新MyCtrl.$inject,但我忘记更新传递给MyCtrl 函数的依赖项:

angular
    .module('my-module')
    .controller('MyCtrl', MyCtrl);

MyCtrl.$inject = [
    'firstDependency',
    'secondDependency',
    'newDependency' // this has been only updated here
];

function MyCtrl(firstDependency, secondDependency, oldDependency) {
    var vm = this;

    // My Controller's code
    // etc...

    function someFunc(x) {
       // here I use newDependency
       return newDependency.doSomething(x);
    }
}   

那么接下来会发生什么?我去更新MyCtrl测试,我实际上记得更新传递给$controller()的依赖项对象:

// MyCtrl testing code
var MyCtrl = $controller('VolunteerResignCtrl', {
    firstDependency: firstDependency,
    secondDependency: secondDependency,
    newDependency: newDependency
});

因此,所有MyCtrl测试都不断传递,所以我认为没有任何破坏。但实际上确实如此。

有人能告诉我这是否可以通过某种方式进行测试并避免我的应用程序在将来失败?

2 个答案:

答案 0 :(得分:1)

这似乎是JS范围而不是Angulars依赖注入的问题。尝试在IIFE中包装您的测试用例和用于它们的函数,因为它们不是,JS会向上移动范围,直到它找到一个名为newDependency的变量,这可能是var myApp = angular.module('myApp', []); myApp.factory('firstDependency', function() { return {} }()); myApp.factory('secondDependency', function() { return {} }()); myApp.factory('newDependency', function() { return {} }()) myApp.controller('MyCtrl', MyCtrl); myApp.controller('TestCtrl', TestCtrl); MyCtrl.$inject = [ 'firstDependency', 'secondDependency', 'newDependency' ]; function MyCtrl(firstDependency, secondDependency, oldDependency) { var vm = this; vm.someFunc = function(x) { // Will work fine as newDependency is defined in a higher scope :c return newDependency.doSomething(x); } } var firstDependency = function() { return {} }(); var secondDependency = function() { return {} }(); var newDependency = function() { return { doSomething: function(x) { return x; } } }() function TestCtrl($scope, $controller) { var test = $controller('MyCtrl', { firstDependency: firstDependency, secondDependency: secondDependency, newDependency: newDependency }); $scope.someFunc = test.someFunc("you're inside the new dependency"); }为什么你的测试正在运行,但它在你的应用程序中崩溃了。

从下面的例子中可以看出

没有 IIFE



<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="TestCtrl">
    {{someFunc}}!
  </div>
</div>
&#13;
var myApp = angular.module('myApp', []);

myApp.factory('firstDependency', function() {
  return {}
}());
myApp.factory('secondDependency', function() {
  return {}
}());
myApp.factory('newDependency', function() {
  return {}
}())

myApp.controller('MyCtrl', MyCtrl);


MyCtrl.$inject = [
  'firstDependency',
  'secondDependency',
  'newDependency'
];

function MyCtrl(firstDependency, secondDependency, oldDependency) {
  var vm = this;
  vm.someFunc = function(x) {
    //Will throw an error, but this time it's a good error because that's what you want!
    return newDependency.doSomething(x);
  }
}

(function(myApp) {


  var firstDependency = function() {
    return {}
  }();
  var secondDependency = function() {
    return {}
  }();
  var newDependency = function() {
    return {
      doSomething: function(x) {
        return x;
      }
    }
  }()

  myApp.controller('TestCtrl', TestCtrl);

  function TestCtrl($scope, $controller) {
    var test = $controller('MyCtrl', {
      firstDependency: firstDependency,
      secondDependency: secondDependency,
      newDependency: newDependency
    });

    $scope.someFunc = test.someFunc("you're inside the new dependency");
  }

})(myApp)
&#13;
&#13;
&#13;

一个IIFE

&#13;
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
  <div ng-controller="TestCtrl">
    {{someFunc}}!
  </div>
</div>
&#13;
var shows = [
{
  id: 1,
  show: 'Simpsons',
  characters: [
  { id: 1, name: 'Bart Simpson', gender: 'Male'},
  { id: 2, name: 'Homer Simpson', gender: 'Male'},
  { id: 3, name: 'Ned Flanders', gender: 'Male'}
]
},
{
  id: 2,
  show: 'Flintstones',
  characters: [
    { id: 1, name: 'Fred Flintstone', gender: 'Male'},
    { id: 2, name: 'Barney Rubble', gender: 'Male'},
    { id: 3, name: 'Wilma Flintstone', gender: 'Female'}
]
}
];

const ShowTable = (props) => {
    return (
    <div>
      <h3>{props.show}</h3>
      <table>
        {props.characters.map((char, index) => (
        <tr key={index}>
          <td>{char.name}</td>
          <td>{char.gender}</td>
        </tr>
            ))}  
      </table>
      <hr />
    </div>
  );
};

const ShowList = (props) => {
    return (
    <div>
      {props.cards.map(card => <ShowTable {...card} />)}
    </div>
  );
}

ReactDOM.render(<ShowList cards={shows} />, mountNode);
&#13;
&#13;
&#13;

答案 1 :(得分:0)

从js角度来看,变量名称并不重要。 以下功能是相同的:

function f(SomeService) {
  SomeService.test();
}

function f(NewService) {
  NewService.test();
}

function f(a) {
  a.test();
}

这就是你需要$ inject的原因 - 因为你传递了字符串。 在$ inject中更改名称后 - 您可以在功能中更改它,但您也可能不会更改它。根本不重要。

相关问题