在Jasmine中使用$q的模拟棱角工厂
Mock angular factory that uses $q in Jasmine
以前肯定有人问过这个问题,但我找不到。我需要模拟一个工厂,但模拟本身需要使用$q,并且在inject()之后调用module()时,我最终陷入了鸡和蛋的境地。
我看了这个问题,它建议做一个spyOn,它适用于服务,因为它是一个单例,但我在工厂返回的函数上调用new 茉莉花测试: 我需要我的mockMyDependencyFactory来使用$q,所以我需要将其封装在inject(函数(…)中,并且我需要在调用模块(函数($provide){… 错误:注入器已创建,无法注册模块 有什么建议可以帮我解决这个问题吗? 或者,如果你认为我的设计有缺陷(我想我可以实例化一个MyDependencyFactory,并在MyConsumingFactory的实例化过程中传递它,而不是使用angular的DI?)我洗耳恭听:)var app = angular.module('app', []);
app.factory('MyDependencyFactory', function() {
return function() {
this.doPromise = function () {
var defer = $q.defer();
//obviously more complicated.
defer.resolve();
return defer.promise;
}
}
});
app.factory('MyConsumingFactory', function(MyDependencyFactory) {
return function() {
var dependency = new MyDependencyFactory();
this.result;
this.doSomething = function () {
dependency.doPromise().then(
function (data) {
this.result = data;
},
function (error) {
console.log(error);
}
);
}
}
});
describe('MyConsumingFactory', function() {
var MyConsumingFactory;
beforeEach(function () {
module('app');
inject( function (_MyConsumingFactory_) {
MyConsumingFactory = _MyConsumingFactory_;
});
inject( function ($q) {
mockMyDependencyFactory = function () {
this.doPromise = function (data) {
var defer = $q.defer();
defer.resolve('mock data');
};
};
});
module( function ($provide) {
$provide.factory('MyDependencyFactory', mockMyDependencyFactory);
});
});
it('works correctly', function () {
MyConsumingFactory.doSomething();
$rootScope.$apply();
expect(MyConsumingFactory.result).toEqual('mock data');
});
});
首先,您对module()
的所有调用都应该在inject()
之前,否则您将得到以下错误:Injector already created, can not register a module!
,即您应该在将模块注入代码之前注册模块。知道了这一点,我们需要在注入之前模拟MyDependencyFactory
,但如果$q
只在inject()
中可用,我们如何在其中获得它?实际上,在角度测试中,将注入的服务分配给测试套件中的全局变量,然后在所有场景中使用它是一种常见的技术:
describe('some suite', function () {
// "global" variables for injected services
var $rootScope, $q;
beforeEach(function () {
module('app');
module(function($provide) {
$provide.factory('MyDependencyFactory', function () {
return function () {
this.doPromise = function (data) {
// use "globals"
var defer = $q.defer();
defer.resolve('mock data');
return defer.promise;
};
};
});
});
inject(function (_$rootScope_, _$q_) {
// assign to "globals"
$rootScope = _$rootScope;
$q = _$q;
});
});
// ....
});
可以在$provide
块中使用$q
的原因是它不会立即使用,只有在调用模拟方法或创建模拟对象的实例时才会使用。到那时,它将被注入并分配给全局变量$q
,并具有适当的值。
如果你想用不同的值多次解析你的承诺,你还可以做一个技巧,那就是创建一个全局变量defer
,并不是在特定的方法中初始化它,而是在某个beforeEach
块中初始化,然后在你的场景中用你在这个特定场景中想要的值来执行defer.resolve('something')
。
在这里你可以看到你的代码的一个工作示例,我做了一些额外的修复来使它工作(有注释)。
注意:我说的是"全局"变量,但它实际上并不像JS术语中那样是全局的,而是特定测试套件中的全局变量。
- 在VanillaJS中模拟模型双向数据绑定
- Angularjs工厂注入错误
- 使用jasmine模拟对服务器的调用
- 如何将参数传递到angularJs中的工厂
- 模拟谷歌地图中的点击
- 为什么只有工厂在棱角分明的网站上被提及
- 使用模拟按键在输入框中自动输入文本
- 模拟chrome.storage.local函数使用Jasmine
- AngularJS:$q.dedefe()不能由工厂方法共享
- 从数据库中检索字段,而不模拟它们
- Angular,函数在(模型)工厂中返回值
- AngularJS错误:提供程序必须从$get工厂方法返回值
- 如何使用异步调用更改工厂的变量
- 将变量传递到工厂
- react testUtils模拟点击单选按钮而不触发onchange
- 使用模拟工厂在茉莉花中测试嵌套承诺
- 如何在使用Jasmine测试工厂时模拟$compile函数
- 模拟工厂控制器测试
- 在Jasmine中使用$q的模拟棱角工厂
- 不能模拟调用另一个工厂方法的工厂方法