如何使用注入服务测试 Angular 1.6 组件?

Posted

技术标签:

【中文标题】如何使用注入服务测试 Angular 1.6 组件?【英文标题】:How to test Angular 1.6 component with injected service? 【发布时间】:2017-06-18 11:38:54 【问题描述】:

我想测试我的 Angular 组件,它在语法上基于 John Papa's styleguide:

'use strict';

 angular.module('MyModule')
    .component('MyCmpnt', MyCmpnt())
    .controller('MyCtrl', MyCtrl);

function MyCmpnt() 

    return 
        restrict: 'E',
        templateUrl: 'myPath/myTemplate.html',
        bindings: 
            foo: '=',
            bar: '<'
        ,
        controller: 'MyCtrl',
        controllerAs: 'vm'
    ;


MyCtrl.$inject = ['MyService'];

function MyCtrl (MyService) 
    // controller logic

如您所见,我想注入 MyService 到控制器中,并在服务 上的一个函数中spy

我的测试代码:

'use strict';

describe('component: MyCmpnt', function () 

    var $componentController,
        MyService;

    beforeEach(module('MyModule'));

    beforeEach(module(function ($provide) 
        $provide.value('MyService', MyService);

        spyOn(MyService, 'serviceFunc').and.callThrough();
    ));

    beforeEach(inject(function (_$componentController_) 
        $componentController = _$componentController_;
    ));


    it('should initiate the component and define bindings', function () 

        var bindings = 
            foo: 'baz',
            bar: []
        ;

        var ctrl = $componentController('MyCmpnt', null, bindings);

        expect(ctrl.foo).toBeDefined();
    );
);

但是,此设置让我遇到以下错误:

TypeError: undefined is not a constructor (evalating '$componentController('MyModule', null, bindings)')

【问题讨论】:

没有“MyModule”组件... @estus:MyModule是一个模块,由一个组件MyCmpnt和对应的控制器MyCtrl组成。不过你是什么意思? 你在做$componentController('MyModule'...,并且没有MyModule组件。这正是错误消息所说的。它是 MyCmpnt。不是我的模块。 你说得对,谢谢,这是一个输入错误,但由于 $componentController 未定义,上述错误仍然存​​在。这意味着注入甚至还没有执行。 这不加起来。 is not a constructor 不仅意味着未定义的东西,而且未定义构造函数。 Angular 仅将构造函数用于控制器和 service 服务。我建议仔细检查您是否在运行的规范中更正了此问题,因为我从上面的代码中看不到此错误的其他合理解释。如果问题仍然存在,请考虑提供可以复制此错误的 plunk/fiddle。顺便说一句,您在上面的代码中未定义 MyService 变量(spyOn(MyService... 会抛出),这意味着发布的代码与实际代码不同。 【参考方案1】:

上面的代码有$componentController('MyModule'...,没有MyModule组件。

MyService 变量在调用spyOn(MyService... 时未定义。这将引发错误,阻止应用程序正确引导。

如果测试平台使用 PhantomJS,这可能会导致 beforeEach 块中的错误抑制,为了正确报告错误,建议使用 Chrome Karma 启动器。

如果问题是 MyService 在定义模拟服务时未定义,则可以将其就地定义为存根:

beforeEach(module(function ($provide) 
    $provide.value('MyService', 
      serviceFunc: jasmine.createSpy().and.callThrough()
    );
));

【讨论】:

以上是关于如何使用注入服务测试 Angular 1.6 组件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular-Fullstack 生成的 Angular 1.5 组件中注入依赖项

是否可以将服务注入 Angular 1.5 组件的 templateUrl 属性?

向组件注入服务后,如何解决加载 Angular 应用程序的问题?

将Angular2服务注入组件基类

使用 Jasmine 间谍进行 Angular 2 组件测试“没有 Http 提供者!”错误

Angular2开发笔记