【问题标题】:How to test properly the usage of $injector?如何正确测试 $injector 的使用?
【发布时间】:2017-10-06 15:30:40
【问题描述】:

我有一项具有以下功能的服务

injectService(serviceToInject: string, methodToInvoke: string){
    let service = this.$injector.get(serviceToInject);
    service[methodToInvoke]();
}

我想知道如何测试这个?我试过这个:

(function () {
'use strict';

describe.only('ServiceA tests', function () {
    let ServiceA;

    beforeEach(angular.mock.module('main'));

    beforeEach(inject(function (_ ServiceA_, _$injector_) {
        ServiceA = _ServiceA_;
        $injector = _$injector_;
    }));

    describe.only('injectServiceAndInvoke', function () {
        it('given a string serviceToInject which is a valid service name and a string methodToInvoke which is valid method name without parameters, it should inject the service and call the method', () => {

            let serviceName = 'validServiceName';
            let methodWithoutParams = 'method';
            let injectedService = $injector.get(serviceName);
            // sandboxSinon.stub(ButtonService.$injector, 'get').withArgs(serviceName).returns(stubbedService);

            let methodToBeCalled = sandboxSinon.stub(injectedService, methodWithoutParams).withArgs(undefined);


            sandboxSinon.stub(ServiceA, 'tokenizeState').withArgs(methodWithoutParams).returns([methodWithoutParams, undefined]);
            ServiceA.injectServiceAndInvoke(serviceName, methodWithoutParams);
            expect(methodToBeCalled.calledOnce).to.equal(true);
        });

    });

});

})();

我得到了错误(正确)服务“validServiceName”不存在。我也尝试对 $injector.get 进行存根,但我不明白应该返回什么存根以及如何从该服务调用该方法。

【问题讨论】:

  • 请提供更多测试代码,以便答案考虑在内。
  • 测试更新
  • 顺便说一句,这感觉很像服务定位器。为什么需要这样做?您是在测试您的实现还是在测试框架?
  • 我想有一种抽象的方式从按钮注入服务,所以我写了这段代码,我想测试一下。

标签: angular unit-testing sinon angularjs-injector sinon-chai


【解决方案1】:

由于$injector服务是全局使用的,所以不能完全通过DI来模拟。这是真正孤立的单元测试的障碍。但并不是一件坏事,因为单个条件模拟不会使测试变得脆弱:

const injectedService = { methodName: sinon.stub() }; 
sinon.stub($injector, 'get');
$injector.get.withArgs('injectedServiceName').returns(injectedService)
$injector.get.callThrough();
ServiceA.injectServiceAndInvoke('injectedServiceName', 'methodName');

expect($injector.get.withArgs('injectedServiceName').calledOnce).to.equal(true);
expect(injectedService.methodName.calledOnce).to.equal(true);
expect(injectedService.methodName.calledWith()).to.equal(true);

但是由于服务具有$injector 作为属性,这为测试提供了一个很好的选择,因为可以在服务实例化之后模拟该属性,而不是模拟真实的$injector.get

const injectedService = { methodName: sinon.stub() }; 
const injectorMock = { get: sinon.stub() };
injectorMock.get.withArgs('injectedServiceName').returns(injectedService);
ServiceA.$injector = injectorMock;
ServiceA.injectServiceAndInvoke('injectedServiceName', 'methodName');

expect(injectorMock.get.withArgs('injectedServiceName').calledOnce).to.equal(true);
expect(injectedService.methodName.calledOnce).to.equal(true);
expect(injectedService.methodName.calledWith()).to.equal(true);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 1970-01-01
    • 2017-10-22
    • 2018-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多