在Ajax方法间谍调用上测试对象的茉莉花状态

Jasmine test state of object on Ajax method spy call

本文关键字:对象 茉莉花 状态 测试 Ajax 方法 间谍 调用      更新时间:2023-09-26

我正在单元测试一个Angular控制器,它使用Rails资源工厂来处理从Rails应用程序获取和发送模型数据。发送是通过模型上的方法完成的,例如(与模型$scope.resource):

$scope.resource.update().then(successHandler, failureHandler);

我在这个方法上有一个间谍,以存根Ajax调用,以便我可以对控制器进行单元测试:

resUpdateSpy = spyOn($scope.resource, 'update').and.callFake(function() { 
  return {then: function(success, failure){ success(resUpdateResponse); }};
});

在我的一个控制器方法中,我希望将资源与某些数据(特别是Stripe数据)一起post。在同一方法中的POST之后,数据将被覆盖,因此之后我无法测试模型的状态。理想情况下,我想这样做:

expect($scope.resource.update).toHaveBeenCalled().whileValueOf($scope.resource.stripeKey).isEqualTo('tok123');

显然,这种方法在香草茉莉中不存在。在Jasmine中是否有一种方法(无论是vanilla还是通过第三方项目)可以在调用给定的spy时测试值的状态?或者是否有另一种方法来测试这种情况-具体来说,模型在其数据发布之前的状态-我错过了?

我在Angular 1.3.14应用上运行Jasmine 2.2.0和茶匙1.0.2。

您可以添加自己的jasme匹配器,您需要的将是

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等。你可以添加自己的自定义匹配器来检查承诺。

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;
    }
}

。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);
}); 

由于您已经让您的间谍将调用转发给一个假函数,因此让该假函数为您存储感兴趣的值:

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');

(取决于间谍设置和断言是否在同一作用域中,用于存储值的变量可能必须不那么本地)