所以基本上没有关于如何在模块上省略配置/运行/提供程序块而没有为单元测试做一些文件加载排序黑客的信息。假设如下:
// dependency chain for providers:
// aaa <- bbb <- ccc
angular.module('module0').provider('bbb', [
'aaaProvider',
function (aaaProvider) {
// aaaProvider definition
...
});
angular.module('module1').provider('ccc', [
'bbbProvider',
function (bbbProvider) {
// bbbProvider definition
...
});
angular.module('module1').controller('controller', [
function () {
// controller definition
}]);
现在假设我们正在为controller
编写单元测试。我们该怎么做?
module('module1');
inject(function ($controller, $rootScope) {
...
});
哎呀,我们遇到了问题。 module('module1')
将触发ccc
的提供商定义,该定义依赖于bbb
,依赖于aaa
。因此,除非我们阻止在ccc
上触发module1
的提供商定义,否则我们将运行与我们进行单元测试的controller
无关的代码。
我们可以使用bbb
表示法来模拟module(function ($provide) { ... });
,这样我们就不需要加载module0
。
但这并没有为ccc
解决这个问题。我没办法阻止它跑。
问题:有没有办法阻止module1
运行ccc
提供商的定义,这与controller
无关我们是单位测试?
到目前为止我尝试过的事情:
在单元测试中覆盖定义:
angular.module('module1').provider('ccc', [function () {}]);
答案 0 :(得分:2)
首先,您需要在app.js中创建两个模块
module1internal - 此模块不具有依赖关系,将用于所有模块 您的应用程序提供商
angular.module('module1internal', []);
module1 - 此模块依赖于module1internal并将包含所有其他依赖项,config和run block
angular.module('module1', ['module1internal','bbbProvider']);
在您的应用中,您应该仅使用内部模块,而不是
angular.module('module1').controller('controller', [
function () {
// controller definition
}]);
你应该使用
angular.module('module1internal').controller('controller', [
function () {
// controller definition
}]);
测试将如下所示:
'use strict';
describe('Controller: TheController', function () {
// mock second level dependencies
beforeEach(function () {
module('module1internal');
module({
bbb: {}
});
});
var TheController, scope,
cccMock;
// mock injected providers
beforeEach(inject(function (_ccc_) {
cccMock = mock(_ccc_);
}));
// Initialise the controller and mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
TheController = $controller('TheController', {
$scope: scope
});
}));
it(' should call ccc functionA on functionThatUsesFunctionA call', function () {
TheController.functionThatUsesFunctionA("someValue");
expect(cccMock.functionA).toHaveBeenCalledWith("someValue");
});
//create spy on all provider's methods(mock it)
function mock(angularServiceToMock) {
for (var i = 0; i < Object.getOwnPropertyNames(angularServiceToMock).length; i++) {
spyOn(angularServiceToMock, Object.getOwnPropertyNames(angularServiceToMock)[i]);
}
return angularServiceToMock;
}
});