单元测试在AngularJS中定义控制器的指令

The*_*idz 18 unit-testing controller directive angularjs karma-runner

我正在尝试使用Karma和Jasmine测试一个指令来完成一些事情.首先是它使用templateUrl,其次是它定义了一个控制器.这可能不是正确的术语,但它在声明中创建了一个控制器.设置Angular应用程序,以便每个单元都包含在自己的模块中.例如,所有指令都包含在模块app.directive中,所有控制器都包含在app.controller中,所有服务都包含在app.service等中.

为了使事情进一步复杂化,在该指令中定义的控制器具有单个依赖关系,并且它包含一个函数,该函数使$ http请求在$ scope上设置值.我知道我可以使用$ httpBackend mock来模拟这个依赖关系来模拟$ http调用并将正确的对象返回给这个函数的调用.我已经在我创建的其他单元测试中做了很多次,并且很好地掌握了这个概念.

下面的代码是用CoffeeScript编写的.

这是我的指示:

    angular.module('app.directive')
      .directive 'exampleDirective', [() ->
        restrict: 'A'
        templateUrl: 'partials/view.html'
        scope: true
        controller: ['$scope', 'Service', ($scope, Service) ->
          $scope.model = {}
          $scope.model.value_one = 1

          # Call the dependency
          Service.getValue()
            .success (data) ->
              $scope.model.value_two = data
            .error ->
              $scope.model.value_two = 0
        ]
      ]
Run Code Online (Sandbox Code Playgroud)

这是依赖服务:

    angular.module("app.service")
      .factory 'Service', ['$http', ($http) ->

      getValue: () ->
        options.method = "GET"
        options.url = "example/fetch"

        $http _.defaults(options)
Run Code Online (Sandbox Code Playgroud)

这是观点:

    <div>
      {{model.value_one}} {{model.value_two}}
    </div>
Run Code Online (Sandbox Code Playgroud)

我已经简化了这一点,因为我的目标只是了解如何连接它,我可以从那里接受它.我用这种方式构造它的原因是因为我最初没有创建它.我正在为现有项目编写测试,但我没有能力以其他方式配置它.我试图编写测试,但不能让它做我想要的.

我想测试以查看值是否绑定到视图,如果可能还要测试控制器是否正在正确创建值.

这是我得到的:

    'use strict'

    describe "the exampleDirective Directive", ->

      beforeEach module("app.directive")
      beforeEach module("app/partials/view.html")

      ServiceMock = {
        getValue : () ->

        options.method = "GET"
        options.url = "example/fetch"

        $http _.defaults(options)
      }

     #use the mock instead of the service
     beforeEach module ($provide) ->
       $provide.value "Service", ServiceMock
       return

     $httpBackend = null
     scope = null
     elem = null

     beforeEach inject ($compile, $rootScope, $injector) ->

     # get httpBackend object
     $httpBackend = $injector.get("$httpBackend")
     $httpBackend.whenGET("example/fetch").respond(200, "it works")

     #set up the scope
     scope = $rootScope

     #create and compile directive
     elem = angular.element('<example-directive></example-directive>')
     $compile(elem)(scope)
     scope.$digest()
Run Code Online (Sandbox Code Playgroud)

我不知道我有多接近,或者这是否正确.我希望能够断言值正确绑定到视图.我已经使用Vojtajina的例子在我的karma.js文件中设置html2js以允许我抓取视图.我已经做了很多研究来找到答案,但我需要一些帮助.希望比我更聪明的程序员可以指出我正确的方向.谢谢.

小智 30

在karma中创建元素,然后使用.controller()带有指令名称的函数来获取控制器.对于您的示例,请使用以下代码替换最后几行:

elem = angular.element('<div example-directive></div>');
$compile(elem)($rootScope);
var controller = elem.controller('exampleDirective');
Run Code Online (Sandbox Code Playgroud)

请注意,根据您如何定义指令,它应该是属性,而不是元素.我也不是百分百肯定,但我认为你不需要scope.$digest;通常我只需要将任何需要应用到scope.$apply(function() {})块中的东西.