AngularJS依赖注入如何与控制器测试一起工作?

时间:2014-02-01 19:35:44

标签: angularjs unit-testing

我正在尝试为一些AngularJS代码编写测试,但是甚至无法运行hello world。假设我的代码如下所示:

var myApp = angular.module("myApp", [])

myApp.controller("MyCtrl", function ($scope) {
    $scope.hello = "world"
})

然后角度文档here表明这样的事情(使用茉莉花)应该有效:

describe("my controller", function () {
    it("should say hello", function () {
        var $scope
        inject(function ($rootScope, $controller) {
            $scope = $rootScope.$new()
            $controller('MyCtrl', {$scope: $scope})
        })
        expect($scope.hello).toBe("world")
    }
}

不幸的是,inject不存在,并且文档中没有关于从何处获取它的提示。因此,文档中的方法不起作用。

稍微远一点,我们找到了$injector,可以由angular.injector创建。从这些文档中可以清楚地看出inject(f)应该是$injector.invoke(f)。因此,我们将其放在代码的顶部并进行更改:

$injector = angular.injector(["myApp"])

不幸的是,这给出了错误“未捕获的错误:来自myApp的未知提供者:$ controllerProvider”,我的google-fu似乎无法解释。

之前当我只测试服务时,我一直在使用这个($injector),它完美无缺。只有在与控制器定义混合时才会出现错误。它可以处理控制器定义或$ injector,但不能同时处理两者。对我来说,这表明存在某种优先级冲突或双重初始化,但我无法弄明白。

那么“未知提供商......”错误意味着什么,以及如何让我的hello world控制器测试工作?如果有人能帮我解决问题,那就太好了。

1 个答案:

答案 0 :(得分:2)

我为你创建了一个可以用于该混凝土控制器的骨架。

describe('my controller', function() {
  var $scope;

  beforeEach(module('app'));

  beforeEach(inject(function($rootScope, $controller) {
    $scope = $rootScope.$new();
    $controller('MyCtrl', { $scope: $scope });
  }));

  it('should contain world', function() {
    expect($scope.hello).toBe('world');
  });

});

在每次测试之前,您注入应用程序模块,在每次测试之前,您将创建一个新范围并实例化您的控制器。然后你只需要编写尽可能多的测试。

我们在每个测试中创建一个新的范围以获得新的状态。我们不想在一次测试中修改某个$ scope,然后又因为你之前修改了$ scope而失败了。

Plunker:http://plnkr.co/edit/4hHqdsvnVwyUhiezpdhW?p=preview

如果您有任何疑问,请发表评论。