【问题标题】:How to access controllerAs namespace in unit test with compiled element?如何使用已编译元素在单元测试中访问 c​​ontrollerAs 命名空间?
【发布时间】:2014-10-01 02:17:38
【问题描述】:

在这个小提琴http://jsfiddle.net/FlavorScape/fp1kktt9/ 中,我尝试在控制器上设置属性,而不是直接设置 $scope。在模板(生产中)中,我们只做 myAliasCtrl.somePropertyList 并且 ng-repeat 工作。

但是,这在测试中不起作用。我不知道如何获取/分配控制器上的属性。

更新: 我的测试环境中一定有一些奇怪的本地化问题,因为我确实让 ng-repeat 工作。请注意如何有两个子元素,即使该属性位于别名控制器上。 http://jsfiddle.net/FlavorScape/2adn983y/2/

但是,我的问题仍然是,我如何获得对该编译控制器的引用来创建间谍?(或者只是获得对别名控制器的引用)?

来源:

angular.module('myApp', [])
.directive('myTestDirective', function () {
    return {
        restrict: 'E',
        scope: {
            myBinding: '='
        },
        replace: true,
        template: '<div ng-if="isRendered">TEST<div ng-repeat="foo in myCtrl.fooList">{{foo}}</div></div>',
        controller: 'myTestController',
        controllerAs: 'myCtrl'
    };
})
.controller('myTestController', function($scope) {
    $scope.isRendered = true;
     // if i reference this, ng-repeat works
    $scope.fooList = ["boob","cat", "Tesla"];
});

describe('myTest directive:', function () {
    var scope, compile, validHTML;

    validHTML = '<div><my-test-directive my-binding="isRendered"></my-test-directive></div>'; //i

    beforeEach(module('myApp'));

    beforeEach(inject(function($compile, $rootScope){
        scope = $rootScope.$new();        
        scope.isRendered = true;

        compile = $compile;
    }));

    function create() {
        var elem, compiledElem;
        elem = angular.element(validHTML);
        compiledElem = compile(elem)(scope);
        scope.$digest();
        return compiledElem;    
    }

    it('should have a scope on root element', function () {  
        var el = create();

        // how to get the controller???
        el.scope().myCtrl.fooList =  ["monkey","apple","Dishwasher"];

        // notice it just has <!-- ng-repeat
        console.log( el );


        expect(el.text()).toContain('TEST');

    });
});

【问题讨论】:

  • 另外,我什至如何访问 myCtrl 实例,比如说,添加一个间谍?
  • 实际上,您会注意到它“编译”了,但控制器从不设置 isRendered 属性。

标签: angularjs unit-testing controller directive


【解决方案1】:

一切都按预期工作:) 你只是试图访问错误的范围。

因为ngIf 创建了一个新范围,您应该访问该范围(因为isRendered 是在该子范围上创建的:

expect(el.children().first().scope().isRendered).toBeTruthy();

这里是updated fiddle。


更新:

您正在使用controllerAs,基本上您将控制器的this 绑定到范围属性。例如。 controllerAs: 'myTestCtrl' 隐式生成 $scope.myTestCtrl = this;(其中 this 是控制器实例。

但是你又在哪里试图访问错误的元素。您需要包装 &lt;div&gt; 的第一个子元素,然后需要它的隔离范围(不是普通范围):

var ctrl = el.children().first().isolateScope().myTestCtrl;

Another updated fiddle

【讨论】:

  • 根据最初的问题,我认为最好避免在模板中迭代 someCtrl.someList (即 controllerAs)——此外,必须定义 $scope 上的视图可访问的任何内容,而不是控制器。它适用于生产,但无法测试。第一次使用 Angular 额头粉碎。
  • 谁说不能测试? Angular 是关于测试的。一切都是可测试的(而且很容易)!
  • 那么如何从单元测试期间编译的指令中获取别名控制器 (controllerAs) 引用?我没有找到这样的方法,这就是为什么我必须重新定义 $scope 上的数据/函数。无法测试别名控制器 + 模板。
  • 我为我的问题添加了一个新的小提琴:如何获取控制器参考?
  • 我意识到你回答了为什么我的测试失败了,但没有回答我原来的问题 =)
猜你喜欢
  • 2019-10-16
  • 2015-01-17
  • 2012-10-03
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多