微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

AngularJS单元测试 – 用于注入依赖项的各种模式

我是单元测试的新手,主要是从我找到的例子中学习.问题是我看到了很多不同的模式,很难理解它们之间的差异.以及如何将这些模式组合到各种用例中.下面是一个这样的模式:

var $rootScope,$window,$location;
    beforeEach(angular.mock.module('security.service','security/loginModal.tpl.html'));

    beforeEach(inject(function(_$rootScope_,_$location_) {
        $rootScope = _$rootScope_;
        $location = _$location_;
    }));

    var service,queue;
    beforeEach(inject(function($injector) {
        service = $injector.get('security');
        queue = $injector.get('securityRetryQueue');
    }));

因此,从这种模式中,我发现Angular核心服务/提供者应该注入下划线模式,其他第三方依赖项或我自己的依赖项应该使用$injector.get()模式完成.这有效吗?我注意到我可以使用Angular核心服务执行$injector.get()并且它仍然可以工作,所以也许只是这样做的惯例?另外,beforeEach中的’security / loginModal.tpl.html’有什么意义(angular.mock.module(‘security.service’,’security / loginModal.tpl.html’));?我知道它是一个添加到模板缓存的HTML模板但是angular.mock.module做了什么呢?

我也看到过这种不太常见的模式,它会在上面的逻辑中抛出一个小扳手:

beforeEach(inject(function($injector,_$location_) {
        security = $injector.get('security');
        $location = _$location_;
    }));

如果我可以像注入$location这样的注入回调添加服务,这似乎是一种更简单的引用依赖关系的方式.我为什么不这样做?

这是另一种模式:

beforeEach(function() {
        module('security.service',function($provide) {
            $provide.value('$window',$window = jasmine.createSpyObj('$window',['addEventListener','postMessage','open']));
        });

        inject(function(security) {
            service = security;
        });
    });

根据我的理解,这种模式的重点是使用模拟的$window初始化“security.service”模块.这是有道理的,但我如何使用以前的模式适应这种模式?即如何模拟’security / loginModal.tpl.html’,如何将我的Angular核心依赖项注入其他依赖项?

最后,我可以和不能在嵌套的描述和注入块中注入什么?假设我无法将模拟服务复制到我正在测试的模块中,这是否安全?那么我可以注入什么以及用例是什么?

如果有一个确定的AngularJS单元测试初始化​​文档源可以帮助回答这些问题,请指出.

解决方法

I’ve gleaned that Angular core services/providers should be injected with the underscore pattern where as other 3rd party dependencies or my own dependencies should be done using the $injector.get() pattern

你可以使用其中之一.下划线模式只是一种方便的方法,可以避免与同名的局部变量发生冲突.考虑以下

var $rootScope,myService,http; // these are local variables

beforeEach(inject(function(_$rootScope_,_myService_,$http) {
    $rootScope = _$rootScope_; // underscores to avoid variable name conflict
    myService = _myService_; // same here with your custom service
    http = $http; // local variable is named differently to service
}));

If I can just add services to the inject callback like this code does with $location,that seems like a simpler way of referencing dependencies. Why should I not do this?

你应该 :)

Also,what is the point of ‘security/loginModal.tpl.html’ in beforeEach(angular.mock.module('security.service','security/loginModal.tpl.html'));?

据我所知,除非你有一个具有该名称的实际模块,例如

angular.module('security/loginModal.tpl.html',[])

这会失败. angular.mock.module只应传递模块名称,实例或匿名初始化函数.

how do I mock ‘security/loginModal.tpl.html’

理想情况下,你不应该.单元测试应测试代码的API …交互点,通常由对象上可公开访问的方法属性定义.

如果您只是想阻止Karma尝试通过HTTP加载模板(通常来自指令测试),您可以使用模板预处理器,如karma-ng-html2js-preprocessor

Lastly,what can I and can’t inject in nested describe and it blocks? Is it safe to assume I can’t retro-inject mocked services to the module I’m testing. So then what can I inject and what are the use cases?

您可以在任何地方(通常在每个和它之前)运行angular.mock.inject.模拟服务应仅在模块或匿名模块初始化函数中配置(如在您的示例中使用$provide和$window),并且通常在您自己的模块(即“security.service”)之后,以覆盖实际服务通过在喷射器中更换它们.一旦运行了inject(),就无法使用mock来回溯替换服务.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐