全局模拟时在Jasmine测试中访问真正的AngularJS服务

时间:2018-12-18 17:27:23

标签: angularjs unit-testing jasmine karma-runner

假设我在AngularJS中提供了一些服务:ComplexService。它在init上执行复杂的操作,并具有复杂的界面...

在Karma / Jasmine测试中,为简化其他组件单元测试,我定义了一个 global [1] 全局模拟(在所有describe声明中业力全球范围):

beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide) {
        $provide.value('ComplexService', buildComplexServiceMock());
    });
});

[1](该决定的原因是避免在每个测试套件中再次声明它-我们大约有50个,每个最终都间接或默认使用该服务)

现在假设,我决定为复杂的服务编写一些单元测试。

我的问题是:现在是否存在一种访问真实服务的方法?(不是模拟的)


我的临时解决方案是使我的服务也可以在全局范围内访问并直接访问它:

function ComplexService(Other, Dependencies) {
    //code here
}

angular.module('MYMODULE')
    .service('ComplexService', ['Other', 'Dependencies', ComplexService]);

window.ComplexService = ComplexService;

但是我对此不满意。 (我不希望生产代码可以在全球范围内访问,也许在测试中除外)

有人可以给我一些线索吗?

编辑

如果可能的话,我想避免的另一件事是直接在测试中指定ComplexService依赖项(以防将来顺序会改变)

临时解决方案,它不好

let complexServiceTestable;

beforeEach(function () {
    inject(function (Other, Dependencies) {
        //If order of dependencies would change, I will have to modify following line:
        complexServiceTestable = window.ComplexService(Other, Dependencies);
    });
});

如果可能的话,我将不胜感激:

let complexServiceTestable;

beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide) {
        //some magic here
    });
});

beforeEach(function () {
    inject(function (ComplexService) {
        complexServiceTestable = ComplexService;
    });
});

2 个答案:

答案 0 :(得分:1)

您可以做的是在测试中显式导入真实的service并用真实的替代$ provide模拟:

import ComplexService from '../your-complex-service-path/ComplexService';

describe('....', function(){

  beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide) {
        $provide.value('ComplexService', ComplexService);
    });
  });

});

我了解设计决策,但也许最好的办法是使一个factory能够注入作为参数,名称或路径传递的任何Service的$provide模拟,这可能有点棘手,但最终可能是一种更具可维护性和描述性的方法。

答案 1 :(得分:0)

感谢@MatiasFernandesMartinez的注释提示,经过一些实验,我终于找到了可行的解决方案(使用提供程序):

在全球业力背景下:

beforeEach(function () {
    angular.mock.module('MYMODULE', function ($provide, ComplexServiceProvider) {
        $provide.value('ComplexServiceBackup', ComplexServiceProvider);
        $provide.value('ComplexService', buildComplexServiceMock());
    });
});

在ComplexService测试中:

describe('ComplexService', function () {
    let complexServiceTestable;

    beforeEach(function () {
        inject(function (ComplexServiceBackup) {
            complexServiceTestable = ComplexServiceBackup.$get();
        });
    });
});