【问题标题】:How to test controller separately?如何单独测试控制器?
【发布时间】:2023-03-29 17:47:01
【问题描述】:

我有一个控制器可以从不同的地方更改一些 DOM。

控制器是:

angular.module('myModule').controller('myController', myController);

function myController() {
    this.addSomeClass = function() {
        $('#idOfSomeElement').addClass('someClass');
    };
}

而且它是这样使用的。里面不同的组件和html。

<div id="idOfSomeElement"></div>
.
.
.
<some-angular-component-here>
    <div ng-controller="myController as ctrl">
        <div ng-click="ctrl.addSomeClass()"></div>
    </div>
</some-angular-component-here>
.
.
.
<using-in-onother-place>
    <div ng-controller="myController as ctrl">
        <div ng-click="ctrl.addSomeClass()"></div>
    </div>
</using-in-onother-place>

我尝试像这样测试它,但我有未定义的 ctrl。

describe('Controller test', function () {
    'use strict';

    var ctrl,
        element;

    beforeEach(inject(function ($rootScope, $compile) {
        var scope = $rootScope.$new();
        angular.element('<div id="idOfSomeElement"></div>' +
                        '<div ng-controller="myController as ctrl">' +
                            '<div id="button" ng-click="ctrl.addSomeClass()"></div>' +
                        '</div>');

        element = $compile(element)(scope);
        scope.$apply();

        // how to get controller here with linked to html?
        ctrl = $controller('myController');
        ctrl = element.controller('myController');

    }));

    it('should add some class', function () {

        var button = $(element).find('#button')[0];
        $(button).trigger('click');

        var someElement = $(element).find('#idOfSomeElement')[0];
        expect(someElement).toHaveSomeClass();
    });
});

如何正确测试这种控制器? 而且我知道在控制器内部操作 DOM 是一件坏事,但我需要对其进行单元测试。

谢谢

【问题讨论】:

  • 测试中的 DOM 固定装置与文档分离,因此 $('#idOfSomeElement') 选择器不会到达固定装置。你最好的办法是模拟$(...)(很可能可以通过存根jQuery init 方法来完成,就像它显示的here)和addClass 方法并监视他们的调用。这就是为什么将 jQuery 与 Angular 混合是一件坏事的原因之一。是的,这不应该在控制器中完成。

标签: angularjs unit-testing compilation controller ng-controller


【解决方案1】:

我认为您忘记将 angular.element 的返回值分配给您的元素属性...

element = angular.element(....

在每个之前完成:

beforeEach(inject(function ($rootScope, $compile) {
    var scope = $rootScope.$new();
    element = angular.element('<div id="idOfSomeElement"></div>' +
                    '<div ng-controller="myController as ctrl">' +
                        '<div id="button" ng-click="ctrl.addSomeClass()"></div>' +
                    '</div>');

    element = $compile(element)(scope);
    scope.$apply();

    // how to get controller here with linked to html?
    ctrl = $controller('myController');
    ctrl = element.controller('myController');

}));

【讨论】:

    猜你喜欢
    • 2014-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-16
    • 1970-01-01
    • 2020-08-12
    • 2017-06-26
    相关资源
    最近更新 更多