gpt4 book ai didi

javascript - AngularJS:如何在配置阶段使用 $q 进行单元测试?

转载 作者:数据小太阳 更新时间:2023-10-29 05:25:48 25 4
gpt4 key购买 nike

我有一个 Angular 服务负责加载 config.json 文件。我想在我的运行阶段调用它,所以我在我的$rootContext 中设置了那个 json,因此,它在未来对每个人都可用。

基本上,这就是我所拥有的:

angular.module('app.core', []).run(function(CoreRun) {
CoreRun.run();
});

我的 CoreRun 服务在哪里:

 angular.module('app.core').factory('CoreRun', CoreRun);

CoreRun.$inject = ['$rootScope', 'config'];

function CoreRun($rootScope, config) {
function run() {
config.load().then(function(response) {
$rootScope.config = response.data;
});
}
return {
run: run
};
}

这工作正常,但当我尝试测试 时出现问题。我想监视我的配置服务,以便它返回一个虚假的 promise 。但是,我做不到,因为在测试的配置阶段,服务不可用,我无法注入(inject) $q。

据我所知,我必须模拟我的配置服务的唯一机会是在配置阶段,因为它是由运行 block 调用的。

到目前为止,我发现的唯一方法是使用我非常不喜欢的 jQuery 生成 promise。

beforeEach(module('app.core'));

var configSample;

beforeEach(module(function ($provide) {
config = jasmine.createSpyObj('config', [ 'load' ]);
config.load.and.callFake(function() {
configSample = { baseUrl: 'someurl' };
return jQuery.Deferred().resolve({data: configSample}).promise();
});
provide.value('config', config);
}));

it('Should load configuration using the correspond service', function() {
// assert
expect(config.load).toHaveBeenCalled();
expect($rootScope.config).toBe(configSample);
});

有没有办法做出更正确的解决方法?

编辑: 可能值得一提的是,这只是在对我的运行 block 进行单元测试时出现的问题。

最佳答案

似乎无法以正确的方式注入(inject) $q,因为 run() block 中的函数会立即触发。 run() block 被认为是 Angular 中的配置阶段,因此测试中的 inject() 仅在配置 block 之后运行,因此即使您 inject() $q 在测试中,它将是 undefined,因为 run() 先执行。

一段时间后,我能够通过一种非常肮脏的解决方法在 module(function ($provide) {}) block 中获取 $q。这个想法是创建一个额外的 Angular 模块并将其包含在应用程序模块之前的测试中。这个额外的模块还应该有一个 run() block ,它将把 $q 发布到一个全局命名空间。 Injector会先调用extra模块的run(),然后调用app模块的run()

angular.module('global $q', []).run(function ($q) {
window.$q = $q;
});

describe('test', function () {

beforeEach(function () {

module('global $q');

module('app.core');

module(function ($provide) {
console.log(window.$q); // exists
});

inject();

});
});

这个额外的模块可以作为测试套件的单独文件包含在规范文件之前。如果您将模块放在测试所在的同一个文件中,那么您甚至不需要使用全局 window 变量,而只需使用文件中的变量即可。

Here is a working plunker (参见“script.js”文件)

第一个解决方案(没有解决问题):

在这种情况下您实际上可以使用$q,但是您必须将它注入(inject)到测试文件中。在这里,您不会真正将它注入(inject)到被测单元中,而是直接注入(inject)到测试文件中以便能够在测试中使用它。所以它实际上并不取决于被测单元的类型:

// variable that holds injected $q service
var $q;

beforeEach(module(function ($provide) {
config = jasmine.createSpyObj('config', [ 'load' ]);

config.load.and.callFake(function() {
var configSample = { baseUrl: 'someurl' };

// create new deferred obj
var deferred = $q.defer();

// resolve promise
deferred.resolve({ data: configSample });

// return promise
return deferred.promise;
});

provide.value('config', config);
}));

// inject $q service and save it to global (for spec) variable
// to be able to access it from mocks
beforeEach(inject(function (_$q_) {
$q = _$q_;
}));

资源:

还有一点要注意:config 阶段和run 阶段是两个不同的东西。 Config block 仅允许使用提供程序,但在 run block 中您可以注入(inject)几乎所有内容(提供程序除外)。更多信息在这里 - Module Loading & Dependencies

关于javascript - AngularJS:如何在配置阶段使用 $q 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31939910/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com