Jasmine不会从$ resource执行回调

时间:2015-01-15 18:06:09

标签: angularjs testing resources tdd jasmine

因此,在编写我不知道如何解决的测试时,我遇到了这个问题:

这是我的控制者:

'use strict';

angular.module('testApp')
  .controller('SettingsExtrasCtrl', function ($scope, $log, Auth, Property, $modal, dialogs, growl) {
    $scope.deleteExtra = function(index) {
      var dlg = dialogs.confirm('Please Confirm', 'Are you sure you want to delete '+$scope.selectedProperty.extras[index].name+'?');
      dlg.result.then(function() {
        Property.removeExtra({ _id : $scope.selectedProperty._id, otherId : $scope.selectedProperty.extras[index]._id }, function(res) {
          $scope.selectedProperty.extras.splice(index,1);
          growl.success("Success message", {title : 'Success'});
        },
        function(err) {
          console.log(err);
        });
      });
    };
});

$ scope.selectedProperty来自父控制器。

这是我的测试:

'use strict';

describe('Controller: SettingsExtrasCtrl', function () {

  // load the controller's module
  beforeEach(module('testApp'));

  var SettingsExtrasCtrl, scope, stateParams, Property, httpBackend;

  var dialogs = {
    confirm: function (title, message) {
      return {
        result: {
          then: function (callback) {
            return callback();
          }
        }
      }
    }
  };

  var fakeProperty = {
    _id : 'propertyId',
    extras : [
      {
        _id : 'extraId',
        name : 'Extra'
      }
    ]
  };

  beforeEach(inject(function ($controller, $rootScope, _Property_, _$httpBackend_, $state, $modal, _dialogs_) {
    scope = $rootScope.$new();
    scope.selectedProperty = fakeProperty;
    stateParams = {propertyId: fakeProperty._id};
    Property = _Property_;
    httpBackend = _$httpBackend_;
    spyOn(Property, 'removeExtra');
    spyOn(_dialogs_, 'confirm').andCallFake(dialogs.confirm);
    SettingsExtrasCtrl = $controller('SettingsExtrasCtrl', {
      $scope: scope,
      $stateParams: stateParams,
      dialogs: _dialogs_,
      $state: $state
    });
  }));


  it('should delete an extra', inject(function(_dialogs_) {
    httpBackend.expectDELETE('/api/properties/' + stateParams.propertyId + '/extras/someextraId').respond(200, '');
    scope.deleteExtra(0);
    expect(_dialogs_.confirm).toHaveBeenCalled();
    expect(Property.removeExtra).toHaveBeenCalled();
    expect(scope.selectedProperty.extras.length).toBe(0);
  }));

});

断言期望(scope.selectedProperty.extras.length).toBe(0);失败因为期望1为0,因为从未调用Property.removeExtra的成功回调。

关于如何解决这个问题的任何想法?

感谢。

1 个答案:

答案 0 :(得分:0)

为了执行承诺,您必须调用摘要周期:

scope.deleteExtra(0);
scope.$digest();

<强> [编辑]

如果是网络电话,您必须查看$httpBackend

基本上它的工作原理如下:

//you can mock the network call
$httpBackend.whenGET('https://url').respond(200);//status code or object

// stuff that make the call
....

$httpBackend.flush();

expect(thing).toBe(stuff);

一点文档:

生产中使用的$ httpBackend始终以异步方式响应请求。如果我们在单元测试中保留了这种行为,我们就必须创建难以编写的异步单元测试,以便跟踪和维护。但是测试模拟也不能同步响应;这会改变被测代码的执行。出于这个原因,模拟$ httpBackend有一个flush()方法,它允许测试显式刷新挂起的请求。这样可以保留后端的异步api,同时允许测试同步执行。