简体   繁体   English

承诺不在Jasmine中解决 - AngularJS

[英]Promise not resolving in Jasmine - AngularJS

I'm trying to test a method that deletes an item from a list after user confirmation. 我正在尝试测试一种在用户确认后从列表中删除项目的方法。

Controller: 控制器:

app.controller('mainCtrl', ['$scope', '$window', 'dataService', function($scope, $window, dataService) {
  var vm = this;

  vm.delete = function(id, index) {
    if($window.confirm('Are you sure?')) {
      dataService.deleteById(id).then(function() {
        vm.list.splice(index, 1)
      });
    }
  };
}]);

Sevice: SEVICE:

app.service('dataService', ['$http', function($http) {
  this.deleteById = function(id) {
    return $http.delete('delete-item?id=' + id);
  };
}]);

Test: 测试:

describe('Testing RecipesController', function() {
  var scope, ctrl, dataServiceMock, q, deferred, window;

  beforeEach(function() {
    dataServiceMock = {
      deleteById: function() {
        deferred = q.defer();
        return deferred.promise;
      }
    };
  });

  beforeEach(function() {
    module('app');
    inject(function($rootScope, $controller, $q, $window) {
      q = $q;
      window = $window;
      scope = $rootScope.$new();
      ctrl = $controller('mainCtrl', {
        $scope: scope,
        dataService: dataServiceMock
      });
    });
  });

  it('should delete recipe if the user clicked "OK"', function() {
    spyOn(window, 'confirm').and.returnValue(true);
    spyOn(dataServiceMock, 'deleteById').and.callThrough();

    var item= {
      id: 2,
      name: 'Shirt'
    };

    ctrl.list = ['Hat', 'Shirt'];
    ctrl.delete(item, 1);

    expect(dataServiceMock.deleteById).toHaveBeenCalled();
    expect(ctrl.list.length).toBe(1);
  });
});

I successfully mocked the confirm dialog and the delete method, and the test to check if the method been called even passes. 我成功地模拟了确认对话框和删除方法,以及检查方法是否被调用甚至通过的测试。
But, The promise.then() isn't working. 但是,promise.then()无效。
After I run the test I got this message "Expected 2 to be 1". 在我运行测试后,我得到了这条消息“预期2为1”。

I see one thing for sure, which is that you never resolve or reject your promise in the data service mock. 我确实看到了一件事,那就是你永远不会在数据服务模拟中解决或拒绝你的承诺。 Try changing the mock to this: 尝试将模拟更改为:

beforeEach(function() {
  dataServiceMock = {
    deleteById: function() {
      deferred = q.defer();
      deferred.resolve({ /* whatever data you want to resolve with */ });
      return deferred.promise;
      // You could also shorten this whole mock function to just:
      //    return $q.resolve({ /* some data */ });
    }
  };
});

Also, don't forget to execute the $digest() function on the $rootScope at the end of your test... you're actually executing it on your controller's scope, NOT the root scope. 另外,不要忘记在测试结束时在$rootScope上执行$digest()函数...你实际上是在控制器范围内执行它,而不是根范围。

Hold onto the actual $rootScope object - change your beforeEach to: 保持实际的$ rootScope对象 - 将您的beforeEach更改为:

var $rScope;

beforeEach(function() {
    module('app');
    inject(function($rootScope, $controller, $q, $window) {
      q = $q;
      window = $window;
      $rScope = $rootScope;
      ctrl = $controller('mainCtrl', {
        $scope: $rootScope.$new(),
        dataService: dataServiceMock
      });
    });
});

Then in your test, execute $digest on the root scope at the end: 然后在测试中,在最后的根作用域上执行$digest

it('should delete recipe if the user clicked "OK"', function() {
  // all your test codez...

  $rScope.$digest();
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM