我正在对Angular控制器进行单元测试,该控制器使用Rails Resource工厂来处理来自Rails应用程序的GETing和POSTing模型数据。 POST通过模型上的方法完成,例如(使用模型$scope.resource
):
$scope.resource.update().then(successHandler, failureHandler);
我有这个方法的间谍来存根Ajax调用,所以我可以对控制器进行单元测试:
resUpdateSpy = spyOn($scope.resource, 'update').and.callFake(function() {
return {then: function(success, failure){ success(resUpdateResponse); }};
});
在我的一个控制器方法中,我希望使用某些数据(特别是条带数据)对资源进行POST。在POST之后,数据将以相同的方法被覆盖,因此我无法在之后测试模型的状态。理想情况下,我想要像:
expect($scope.resource.update).toHaveBeenCalled().whileValueOf($scope.resource.stripeKey).isEqualTo('tok123');
显然,香草茉莉花中不存在这种方法。在调用给定的间谍时,Jasmine(通过vanilla或通过第三方项目)是否有办法测试值的状态?还是有另一种方法来测试这种情况 - 特别是模型在数据POST之前的状态 - 我错过了吗?
我在Angular 1.3.14 app上使用Teaspoon 1.0.2运行Jasmine 2.2.0。
答案 0 :(得分:3)
你可以添加自己的jasime匹配器,你需要的那个
jasmine.Matchers.prototype.toBeResolvedWith = function() {
var done, expectedArgs;
expectedArgs = jasmine.util.argsToArray(arguments);
if (!this.actual.done) {
throw new Error('Expected a promise, but got ' + jasmine.pp(this.actual) + '.');
}
done = jasmine.createSpy('done');
this.actual.done(done);
this.message = function() {
if (done.callCount === 0) {
return ["Expected spy " + done.identity + " to have been resolved with " + jasmine.pp(expectedArgs) + " but it was never resolved.", "Expected spy " + done.identity + " not to have been resolved with " + jasmine.pp(expectedArgs) + " but it was."];
} else {
return ["Expected spy " + done.identity + " to have been resolved with " + jasmine.pp(expectedArgs) + " but was resolved with " + jasmine.pp(done.argsForCall), "Expected spy " + done.identity + " not to have been resolved with " + jasmine.pp(expectedArgs) + " but was resolved with " + jasmine.pp(done.argsForCall)];
}
};
return this.env.contains_(done.argsForCall, expectedArgs);
};
此处更多https://gist.github.com/gr2m/2191748
评论后更新:
基本上jasmine支持自定义匹配器。建立匹配器中的一些是toBe,toEqual等。您可以添加自己的custom matcher来检查承诺。
var customMatchers = {
toHaveBeenResolved: function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
var result = {};
// do you comparison logic here
result.pass = true/false;
result.message = 'some message about test result';
return result;
}
}
this.actual是一个承诺,您可以像这样解决它
result = {};
promise.then(function(value){
result.value = value;
result.status = 'Resolved';
}, function(value){
result.value = value;
result.status = 'Rejected';
});
一旦声明了自定义匹配器,就会在beforeEach回调中的测试用例中使用它。
beforeEach(function() {
jasmine.addMatchers(customMatchers);
});
答案 1 :(得分:1)
正如你已经让你的间谍转发了一个伪造的函数,让那个假函数为你存储感兴趣的值:
var scopeResourceStripeKeyDuringSpyCall = '(spy not called, yet)';
resUpdateSpy = spyOn($scope.resource, 'update').and.callFake(function() {
scopeResourceStripeKeyDuringSpyCall = $scope.resource.stripeKey;
return {then: function(success, failure){ success(resUpdateResponse); }};
});
然后只需检查断言中存储的值:
expect(scopeResourceStripeKeyDuringSpyCall).toEqual('tok123');
(根据间谍设置和断言是否在同一范围内,用于存储值的变量可能必须更少本地。)