有啥方法可以根据参数修改 Jasmine 间谍?
Posted
技术标签:
【中文标题】有啥方法可以根据参数修改 Jasmine 间谍?【英文标题】:Any way to modify Jasmine spies based on arguments?有什么方法可以根据参数修改 Jasmine 间谍? 【发布时间】:2013-04-18 09:06:48 【问题描述】:我想测试一个函数,它使用不同的参数两次调用外部 API 方法。我想用 Jasmine 间谍模拟这个外部 API,并根据参数返回不同的东西。茉莉花有没有办法做到这一点?我能想到的最好的方法是使用 andCallFake 进行破解:
var functionToTest = function()
var userName = externalApi.get('abc');
var userId = externalApi.get('123');
;
describe('my fn', function()
it('gets user name and ID', function()
spyOn(externalApi, 'get').andCallFake(function(myParam)
if (myParam == 'abc')
return 'Jane';
else if (myParam == '123')
return 98765;
);
);
);
【问题讨论】:
为什么你觉得and.callFake
是个黑客?对我来说似乎是一个很好/最好的答案。
【参考方案1】:
在 Jasmine 3.0 及以上版本中,您可以使用withArgs
describe('my fn', function()
it('gets user name and ID', function()
spyOn(externalApi, 'get')
.withArgs('abc').and.returnValue('Jane')
.withArgs('123').and.returnValue(98765);
);
);
对于早于 3.0 的 Jasmine 版本,callFake
是正确的方法,但您可以使用对象来保存返回值来简化它
describe('my fn', function()
var params =
'abc': 'Jane',
'123': 98765
it('gets user name and ID', function()
spyOn(externalApi, 'get').and.callFake(function(myParam)
return params[myParam]
);
);
);
根据 Jasmine 的版本,语法略有不同:
1.3.1:.andCallFake(fn)
2.0:.and.callFake(fn)
资源:
withArgs docs callFake docs andCallFake vs and.callFake【讨论】:
现在是and.callFake
- jasmine.github.io/2.2/…>
我必须返回不同的承诺,所以返回看起来略有不同:return q.when(params[myParam]);。否则,这是解决我的问题的一个点。我梦想的解决方案是更改“and.returnValue”调用。
感觉 jasmine 应该有更好的声明方式。喜欢spyOn(fake, 'method').withArgs('abc').and.returnValue('Jane')
和spyOn(fake, 'method').withArgs('123').and.returnValue(98765)
。
@jrharshath .withArgs
在 jasmine 2.0 中不适合我
.withArgs
并不真正可用 - 我的意思是这样的方法在编写测试时会有意义。【参考方案2】:
您也可以使用$provide
创建间谍。并模拟使用and.returnValues
而不是and.returnValue
来传入参数化数据。
根据 Jasmine 文档: 通过将间谍与
and.returnValues
链接,对函数的所有调用将按顺序返回特定值,直到它到达返回值列表的末尾,此时它将为所有后续调用返回 undefined。
describe('my fn', () =>
beforeEach(module($provide =>
$provide.value('externalApi', jasmine.createSpyObj('externalApi', ['get']));
));
it('get userName and Id', inject((externalApi) =>
// Given
externalApi.get.and.returnValues('abc','123');
// When
//insert your condition
// Then
// insert the expectation
));
);
【讨论】:
这是正确的答案,因为测试应该始终准确地知道间谍将如何被调用,因此应该只使用returnValues
来支持多个调用
只是为了澄清 akhouri 的回答:此方法仅在 externalApi.get.and.returnValues('abc','123')
在 it
函数中调用时有效。否则,如果您设置一个值列表,否则它永远不会起作用,因为运行测试的顺序是不可预测的。事实上,测试不应该依赖于它们的执行顺序。【参考方案3】:
在我的例子中,我有一个正在测试的组件,在它的构造函数中,有一个配置服务,其中有一个名为 getAppConfigValue 的方法,该方法被调用两次,每次使用不同的参数:
constructor(private configSvc: ConfigService)
this.configSvc.getAppConfigValue('a_string');
this.configSvc.getAppConfigValue('another_string');
在我的规范中,我在 TestBed 中提供了 ConfigService,如下所示:
provide: ConfigService,
useValue:
getAppConfigValue: (key: any): any
if (key === 'a_string)
return 'a_value';
else if (key === 'another_string')
return 'another_value';
as ConfigService
所以,只要 getAppConfigValue 的签名与实际的 ConfigService 中指定的相同,函数内部的作用是可以修改的。
【讨论】:
以上是关于有啥方法可以根据参数修改 Jasmine 间谍?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Jasmine 间谍进行 Angular 2 组件测试“没有 Http 提供者!”错误