Unit testing 当使用jasmine进行单元测试时,如何在AngularJS中模拟服务?
假设我有一个服务Unit testing 当使用jasmine进行单元测试时,如何在AngularJS中模拟服务?,unit-testing,angularjs,jasmine,Unit Testing,Angularjs,Jasmine,假设我有一个服务商店,它依赖于两个有状态的服务时间表和仓库。如何将不同版本的schedule和warehose注入shop进行单元测试 这是我的服务: angular.module('myModule').service('shop', function(schedule, warehouse) { return { canSellSweets : function(numRequiredSweets){ return schedule.isSh
商店
,它依赖于两个有状态的服务时间表
和仓库
。如何将不同版本的schedule
和warehose
注入shop
进行单元测试
这是我的服务:
angular.module('myModule').service('shop', function(schedule, warehouse) {
return {
canSellSweets : function(numRequiredSweets){
return schedule.isShopOpen()
&& (warehouse.numAvailableSweets() > numRequiredSweets);
}
}
});
以下是我的模拟:
var mockSchedule = {
isShopOpen : function() {return true}
}
var mockWarehouse = {
numAvailableSweets: function(){return 10};
}
以下是我的测试:
expect(shop.canSellSweets(5)).toBe(true);
expect(shop.canSellSweets(20)).toBe(false);
你可以在这里查看更多信息 您希望利用$provide服务。就你而言
$provide.value('schedule', mockSchedule);
模块是由“角度模拟”模块提供的功能。如果您传入一个字符串参数,则会加载一个具有相应名称的模块,并且所有提供程序、控制器、服务等都可用于规范。通常,它们是使用inject函数加载的。如果传入回调函数,将使用Angular的$injector服务调用它。然后,该服务查看传递给回调函数的参数,并尝试推断应该将哪些依赖项传递给回调函数 对于CoffeeScript,我遇到了一些问题,因此我在结尾使用了null:
beforeEach ->
module ($provide) ->
$provide.value 'someService',
mockyStuff:
value : 'AWESOME'
null
改进Atilla的回答并直接回答KevSheedy的评论,在
模块('myApplicationModule')
的上下文中,您将执行以下操作:
beforeEach(module('myApplicationModule', function ($provide) {
$provide.value('schedule', mockSchedule);
}));
我最近发布了ngImprovedTesting模块,该模块将使AngularJS方式的模拟测试更容易 在您的示例中,您只需在Jasmine测试中替换
beforeEach(module('myModule'));
。。。与
beforeEach(ModuleBuilder.forModule('myModule').serviceWithMocks('shop').build());
有关ngImprovedTesting的更多信息,请查看其介绍性博文:
在模块上放置模拟更简单,如下所示:
beforeEach(function () {
module('myApp');
module({
schedule: mockSchedule,
warehouse: mockWarehouse
}
});
});
您可以使用注入获取对这些模拟的引用,以进行测试前操作:
var mockSchedule;
var mockWarehouse;
beforeEach(inject(function (_schedule_, _warehouse_) {
mockSchedule = _schedule_;
mockWarehouse = _warehouse_;
}));
我希望我的回答没有那么没用,但是你可以通过
$provide.service
beforeEach(() => {
angular.mock.module(
'yourModule',
($provide) => {
$provide.service('yourService', function() {
return something;
});
}
);
});
当您使用jasmine时,有另一种方法可以用jasmine的间谍来模拟呼叫() 使用这些函数,您可以成为函数调用的目标,并在需要时允许调用原始对象。它避免了用$provide和mock实现阻塞测试文件的顶部 在每次测试之前,我都会有如下内容:
var mySchedule, myWarehouse;
beforeEach(inject(function(schedule, warehouse) {
mySchedule = schedule;
myWarehouse = warehouse;
spyOn(mySchedule, 'isShopOpen').and.callFake(function() {
return true;
});
spyOn(myWarehouse, 'numAvailableSweets').and.callFake(function() {
return 10;
});
}));
这应该以与$PROFECT机制类似的方式工作,注意您必须提供注入变量的本地实例来监视。为了避免cooffeescript隐式返回,您只需在函数末尾添加一个
return
语句,因此,函数不返回null
,而只是不返回任何内容。看,如果你说“return”,它将返回“undefined”--但这两种方法都可以很好地工作,而且这种方法短2个字符;)--不管是哪种方式,你都应该在这条线上添加一条评论,因为无意中删除它的那个家伙正遭受着与你当初一样的痛苦。这修复了我的(令人沮丧的)问题。基本上,只要我添加$provideformocking,我的angular.mock.inject就不再运行/工作。返回null使它们可以很好地配合使用。因此,这种语法基本上可以模拟myApplicationModule
中的时间表(或任何服务、控制器、工厂)?您真的需要额外的周边函数吗?也就是说,是否可以在每次调用之前将模块
函数直接传递到?实际上不需要围绕模块
调用的函数。
var mySchedule, myWarehouse;
beforeEach(inject(function(schedule, warehouse) {
mySchedule = schedule;
myWarehouse = warehouse;
spyOn(mySchedule, 'isShopOpen').and.callFake(function() {
return true;
});
spyOn(myWarehouse, 'numAvailableSweets').and.callFake(function() {
return 10;
});
}));