AngularJS (1.5) 中的单元测试控制器,当这些控制器作为模块导出时(头痛...)

Unit testing controllers in AngularJS (1.5), when those controllers are exported as modules (headache...)

所以,我正在尝试 运行 在 Angular 1.5 应用程序中的控制器上进行单元测试,以便从现在开始我可以为所有其他控制器进行 TDD。但是,它变得有点头疼。

所有讨论测试 ng-controller 的教程和博客文章似乎都是通过注入他们的应用程序使用的控制器,并注入他们的实际应用程序来实现的。

我正在构建的应用程序为其控制器导出了一个函数,我想知道这是否是导致我头疼的原因。

这是一个例子:

// Controller file
const myController = (app) => {
  const controller = app.controller('MyCtrl', ['$scope', 'SomeService', ($scope, SomeService) => {
    // Stuff in here
}])

  return controller
}

module.exports = {
  init: myController
}

上面的调用方式:

myController.init(angular.module('myApp'))

因此,在我对该控制器的单元测试中,我尝试以这种方式进行设置:

// Test file
const myController = require('../path/to/myController')
const app = angular.module('testModule', [])
myController.init(app)

describe('Controller tests: ', () => {
  it('should work', inject(($controller) => {
    const testMyCtrl = $controller('MyCtrl', {
      $scope: {}
    })
    assert.equal(true, true)
  }
}

但是,当我尝试测试这个(使用 Karma 和 Mocha)时,我得到:

Argument 'MyCtrl' is not a function, got undefined

遗憾的是,我对 AngularJS 中的单元测试不是很熟悉,我只是在努力加入这些点。有没有人有任何明智的建议?

好的,现在整理一下。我最终修改了我的控制器文件,使其看起来像这样:

// Controller file
const MyCtrl = ($scope, SomeService) => {
  // Stuff here
}

module.exports = myCtrl

然后我在我的 app.js 文件中实例化它,如下所示:

import MyCtrl from './path/to/controller'
MyCtrl.$inject = ['$scope', SomeService] // Where 'SomeService' is also imported into this file
const app = angular.module('MyApp', [])
app.controller('MyCtrl', MyCtrl)

然后在我的单元测试中,我有一个 'test-app.js' 文件,它创建测试应用程序并以相同的方式实例化它需要的服务和控制器(这可能真的没有必要,它也可以正常工作使用真实的应用程序,但将它们完全分开感觉更好)。然后在测试我的控制器的文件中,我有;

// Controller's unit test file
describe('MyCtrl tests: ', () => {
  var myCtrl
  var $scope
  var SomeService

  beforeEach(angular.mock.module('testApp')) // testApp is created in test-app.js
  beforeEach(angular.mock.inject(($controller, $rootScope, _SomeService_) => {
    SomeService = _SomeService_
    $scope = $rootScope.$new()
    MyCtrl = $controller('MyCtrl', {
      $scope: $scope,
      SomeService: SomeService
    }
  }

  // tests...
})

现在我所有的测试都可以访问控制器。希望这对将来的某人有用。 :)