单元测试在 AngularJS 中定义控制器的指令 [英] Unit testing a directive that defines a controller in AngularJS

查看:18
本文介绍了单元测试在 AngularJS 中定义控制器的指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

让事情更复杂的是,在该指令中定义的控制器具有单个依赖项,它包含一个函数,该函数发出 $http 请求以在 $scope 上设置值.我知道我可以使用 $httpBackend mock 来模拟这个依赖项来模拟 $http 调用并将正确的对象返回给这个函数的调用.我已经在我创建的其他单元测试中多次执行此操作,并且对这个概念有很好的掌握.

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

这是我的指令:

 angular.module('app.directive').directive 'exampleDirective', [() ->限制:'A'templateUrl: 'partials/view.html'范围:真实控制器:['$scope', 'Service', ($scope, Service) ->$scope.model = {}$scope.model.value_one = 1# 调用依赖服务.getValue().成功(数据)->$scope.model.value_two = 数据.错误 ->$scope.model.value_two = 0]]

这里是依赖服务:

 angular.module("app.service").factory '服务', ['$http', ($http) ->getValue: () ->options.method = "GET"options.url = "示例/获取"$http _.defaults(选项)

这是视图:

 

{{model.value_one}} {{model.value_two}}

我已经简化了很多,因为我的目标只是了解如何连接它,我可以从那里开始.我以这种方式构建它的原因是因为我最初没有创建它.我正在为现有项目编写测试,但我无法以任何其他方式对其进行配置.我已经尝试编写测试,但无法让它做我想做的事.

我想测试一下值是否绑定到视图,如果可能的话还测试一下控制器是否正确创建了值.

这是我所拥有的:

 '使用严格'描述exampleDirective 指令",->beforeEach 模块(app.directive")beforeEach 模块(app/partials/view.html")服务模拟 = {getValue : () ->options.method = "GET"options.url = "示例/获取"$http _.defaults(选项)}#使用模拟代替服务beforeEach 模块 ($provide) ->$provide.value "服务", ServiceMock返回$httpBackend = null范围 = 空元素 = 空beforeEach 注入 ($compile, $rootScope, $injector) -># 获取httpBackend对象$httpBackend = $injector.get("$httpBackend")$httpBackend.whenGET("example/fetch").respond(200, "它有效")#设置范围范围 = $rootScope#创建和编译指令elem = angular.element('<example-directive></example-directive>')$compile(elem)(范围)范围.$digest()

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

解决方案

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

elem = angular.element('

');$compile(elem)($rootScope);var controller = elem.controller('exampleDirective');

注意,鉴于您如何定义指令,它应该是按属性,而不是作为元素.我也不是 100% 确定,但我不认为你需要 scope.$digest; 通常我只是把任何需要应用到 scope.$apply(function() {}) 块.

I'm trying to test a directive using Karma and Jasmine that does a couple of things. First being that it uses a templateUrl and second that it defines a controller. This may not be the correct terminology, but it creates a controller in its declaration. The Angular application is set up so that each unit is contained within its own module. For example, all directives are included within module app.directive, all controllers are contained within app.controller, and all services are contained within app.service etc.

To complicate things further, the controller being defined within this directive has a single dependency and it contains a function that makes an $http request to set a value on the $scope. I know that I can mock this dependency using $httpBackend mock to simulate the $http call and return the proper object to the call of this function. I've done this numerous times on the other unit tests that I've created, and have a pretty good grasp on this concept.

The code below is written in CoffeeScript.

Here is my directive:

    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
        ]
      ]

Here is the dependency service:

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

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

        $http _.defaults(options)

Here is the view:

    <div>
      {{model.value_one}} {{model.value_two}}
    </div>

I've simplified this quite a bit, as my goal is only to understand how to wire this up, I can take it from there. The reason I'm structuring it this way is because I did not initially create this. I'm working on writing tests for an existing project and I don't have the ability to configure it any other way. I've made an attempt to write the test, but cannot get it to do what i want.

I want to test to see if the values are being bound to the view, and if possible to also test to see if the controller is creating the values properly.

Here is what I've got:

    '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()

I don't know how close I am, or if this is even correct. I want to be able to assert that the values are bound to the view correctly. I've used Vojtajina's example to set up html2js in my karma.js file to allow me to grab the views. I've done a lot of research to find the answer, but I need some help. Hopefully a programmer wiser than I can point me in the right direction. Thank you.

解决方案

Create the element in karma, then use the .controller() function with the name of your directive to grab the controller. For your example, replace the last couple of lines with these:

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

Note, that given how you defined your directive, it should be by attribute, and not as an element. I'm also not 100% sure, but I don't think you need the scope.$digest; usually I just put anything that needs to be applied into a scope.$apply(function() {}) block.

这篇关于单元测试在 AngularJS 中定义控制器的指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆