【问题标题】:How to get angular controller reference from compiled element in unit tests?如何从单元测试中的已编译元素中获取角度控制器参考?
【发布时间】:2014-09-07 09:21:03
【问题描述】:

在放弃 ngMockE2E 能够从 $httpBackend 提供正确的 passThrough() 之后,我求助于手动将模板添加到缓存中。如果我只想“测试”我的模板,这似乎很有效。但是,假设我想在被调用的控制器上测试一些条件(通过指令),我如何获得对它的引用?

describe('RedactedFilter ', function() {

    var ctrl, filterModel,createController;

    var $httpBackend,$scope,template, $templateCache,$compile,$rootScope, $compile;

    beforeEach(module('RedactedApp.Services'));
    beforeEach(module('RedactedApp.Controllers'));
    beforeEach(module('RedactedApp.Models'));

    beforeEach(inject(function($templateCache,_$compile_,_$rootScope_) {

        //assign the template to the expected url called by the directive and put it in the cache
        template = $templateCache.get('src/main/app/components/redactedFilter/redacted-filter.tpl.html');
        $templateCache.put('src/main/app/components/redactedFilter/redactedFilter-filter.tpl.html',template);

        $compile = _$compile_;
        $rootScope = _$rootScope_;
    }));



    beforeEach(inject(function ($controller, $rootScope,_$q_, $injector, _$compile_) {

        $scope = $rootScope.$new();
        $httpBackend = $injector.get('$httpBackend');
        $compile = _$compile_;

        filterModel = $injector.get('RedactedFilterModel');
    }));

    it('should default to tab 0', function() {

        var formElement = angular.element('<redacted-filter></redacted-filter>');
        var element = $compile(formElement)($rootScope);
        $rootScope.$digest();

        var ctrl = element.controller();

        //ctrl is undefined
        expect(ctrl.selectedTab).toEqual(0);
    });

});

请注意,它并不是说函数 controller() 是未定义的,而是调用它的结果。我的指令将replace 设置为false,所以我认为嵌入隐藏元素不是问题。

这是我的良好措施指令:

angular.module('RedactedApp.Directives').directive('redactedFilter', function(){
        return {
            restrict: 'E',
            replace: false,
            templateUrl: '../../main/app/components/redactedFilter/redacted-filter.tpl.html'
        };
    });

【问题讨论】:

  • 您不需要访问指令的控制器。您正在将已编译的指令应用于范围,您可以检查范围以查看您期望的值是否已设置。
  • 在这种情况下我得到未定义,因为我使用控制器,而不是依赖范围。我认为更好的方法是编译元素并将其推入显式控制器引用中?
  • 仅仅因为您使用控制器并不意味着您没有使用 $scope,它只是没有被注入。在上述情况下,因为您将指令应用于 $rootScope,我会检查要在 $rootScope 上定义的 selectedTab 的值。 (旁注:我会使用 $rootScope.$new() 而不是 $rootScope)
  • 好吧,我想我在这里错过了一大步,我必须对模板进行预处理,然后将其推送到缓存中。这实际上并没有加载它 =(。我真的希望他们修复 passThrough,这样我们就可以像理智的人一样加载模板。或者我错过了什么?
  • "您可以检查范围以查看您期望的值是否已设置。"我将如何在控制器上使用间谍?

标签: angularjs unit-testing directive


【解决方案1】:

首先,在运行测试之前,使用 ng-html2j 或 ng-templates 将模板推送到模板缓存中。

然后将模板编译成元素,并将它们推入控制器进行测试:

beforeEach(inject(function($templateCache,_$compile_,_$rootScope_, _$controller_) {

    //get the template from the cache
    template = $templateCache.get('src/main/app/components/someController/widget-search.tpl.html');

    $compile = _$compile_;
    $rootScope = _$rootScope_;
    $controller = _$controller_;

    //compile it
    element = $compile(template)($rootScope);
}));

 //then shove your compiled element into your controller instance



it( 'should be instantiated since it does not do much yet', function(){

            ctrl = $controller('SomeController',
                {
                    $scope: $rootScope.$new(),
                    $element: element
                });

            expect( ctrl.hasInstance).toBeTruthy();

        });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-10
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 2017-10-09
    • 1970-01-01
    • 2015-09-13
    相关资源
    最近更新 更多