【问题标题】:Unit Testing with AngularJS 1.5+ using $componentController - Double data binding使用 $componentController 使用 AngularJS 1.5+ 进行单元测试 - 双重数据绑定
【发布时间】:2017-08-31 16:10:46
【问题描述】:

我目前的测试代码有问题。 一个例子胜过一万个字所以就在这里。

describe('Initilazing', () => {

    let $componentController, scope;
    beforeEach(inject((_$componentController_, _$rootScope_) => {
        $componentController = _$componentController_;
        scope = _$rootScope_.$new();
        scope.name = 'Testing...';
    }));

    it('Should have the parent scope double binded', () => {
        let $ctrl = $componentController('sasInput', scope, { api: scope.sasInput });
        $ctrl.onInit();

        scope.$apply();
        expect(scope.sasInput).not.toBeUndefined();
    });
});


class SasInputController() {
    constructor() {
      'ngInject';
    }


    $onInit() {
        this.api = { clear: this.clear.bind(this) };
    }

    clear() {
        this.input = null;
    }
}

export default {
    ...
    bindings: {
        api: '='
    }
}

这是交易,在我的组件中,scope.sasInput 应该使用 $onInit 上的当前组件 api 进行更新。但事实并非如此。 我在这里做错了什么?

你能帮忙吗? 谢谢。

【问题讨论】:

  • 能否请您显示您的组件定义和$onInit组件控制器的处理程序?
  • 已编辑。为清楚起见,我没有放置所有导出参数。绑定是这里有趣的一个。
  • 在执行this.api = { clear: ... 时,您将失去对传递给组件的scope 对象的引用。使用更复杂的模型可以帮助您避免这种情况。看看this gist with mentioned approach,希望对你有帮助。
  • 我明天上班试试这个。我一测试这个就回来找你:)如果这可行,我不明白为什么tbh。因为代码在浏览器中完美运行。

标签: angularjs jasmine jestjs


【解决方案1】:

$componentController 所做的只是从组件定义中获取一个控制器并实例化它。如果$onInit需要测试,直接调用即可:

$ctrl.$onInit();

$onInit 是生命周期钩子,是编译过程的一部分。为了对一个组件进行整体测试,应该使用$compile 编译它,就像任何其他指令一样。

【讨论】:

  • 是的,对不起,这是我的错误。我忘了把 $onInit() 调用放在帖子上。仍然无法正常工作'
  • 控制器无法将更改传播回scope,因为它没有引用它。您不能使用 $componentController 来测试双向 = 绑定。使用 $ 编译。 $componentController 用于测试类逻辑。
  • 我选择了 $componentController,因为使用 $compile 引发了关于不安全模板 URL 的错误。我们使用 $templateCache 和 gulp 将 HTML 文件转换为包含所有模板缓存定义的 JS 模块。而且我不知道如何使用 Jasmine tbh 进行这项工作:(
【解决方案2】:

正如@estus 所述(感谢他),您无法使用$componentController 测试双向数据绑定。您必须创建一个包含您的组件的新angular.Element,并使用$compile 调用scope.$digest() 来执行此操作。 这是最终的解决方案

... // previously created a scope with $rootScope.$new() ($rootScope injected with inject())
it("should double bind", () => {
    const element = angular.element("<your-component two-way='api'></your component>");
    inject(($compile) => {
        const compiledElement = $compile(element)(scope);
        scope.$digest();
        expect(scope.api).not.toBeUndefined();
    });
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-11
    • 2016-10-07
    • 1970-01-01
    • 2013-06-29
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-08-07
    相关资源
    最近更新 更多