首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有承诺的spyOn

有承诺的spyOn
EN

Stack Overflow用户
提问于 2015-04-09 01:17:01
回答 1查看 4.6K关注 0票数 1

我有以下的功能,我想监视.但它包含了一个承诺..。但我得到的是TypeError:“未定义”不是一个对象(计算'modalService.showModal({},modalOptions).then')

因为我当然只有spyOn(modalService,'showModal')

我怎么解释这个承诺呢??

代码语言:javascript
复制
_modalService = {
    close: function (value) { console.log(value) },
    dismiss: function (value) { console.log(value) },
    showModal: function (value) { console.log(value) }
};

spyOn(_modalService, 'close');
spyOn(_modalService, 'dismiss');
spyOn(_modalService, 'showModal');

控制器功能:

代码语言:javascript
复制
user.resetPassword = function () {
            var modalOptions = {
                closeButtonText: 'Cancel',
                actionButtonText: 'Reset',
                headerText: 'Reset Password',
                bodyText: 'Are you sure you want to reset the users password?'
            };

            modalService.showModal({}, modalOptions).then(function (result) {
                if (result === 'ok') {
                    userDataService.resetPassword(user.data).then(function (result) {
                        $scope.$emit('showSuccessReset');
                    });

                };
            });
        };

这是我的单元测试:

代码语言:javascript
复制
it('should allow the users password to be reset', function () {
        var controller = createController();
        controller.resetPassword();
        $httpBackend.flush();
    })

*

所以我把它改为:

代码语言:javascript
复制
 //Create a fake instance of the modal instance. TO ensure that the close is called
        _modalService = {
            close: function (value) { console.log(value) },
            dismiss: function (value) { console.log(value) },
            showModal: function (value) { console.log(value) }
        };

        spyOn(_modalService, 'close');
        spyOn(_modalService, 'dismiss');
        spyOn(_modalService, 'showModal').and.callThrough();

        _modalService.showModal = function() {
                var deferred = $q.defer();
                deferred.resolve('Remote call result');
                return deferred.promise;   
            };

老实说,我不确定我能不能解释一下。虽然我理解所有异步的东西..。我不知道茉莉花是怎么用这个来让一切正常运转的。有人能解释一下流程吗?而且我觉得语法不对..。你通常是怎么写这个的,这样看起来就更干净了.??

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-04-09 02:57:45

当您需要模拟一个返回承诺的函数时,您有两个选项:

  1. 返回一个被嘲弄的承诺(一个类似承诺的物体);
  2. 回报一个真正的承诺。

我建议#2,因为它更容易,而且您不必担心复制整个承诺API。换句话说,不值得嘲笑承诺本身。

现在谈谈茉莉花:你只需要在你已经有了一个对象(不是一个模拟)并且你想窥探它的一个方法(没有双关语)的时候才需要使用spyOn。在您的示例中,整个对象都是假的,因此可以使用jasmine.createSpyObj

以下示例应使上述所有内容更加清晰:

SUT

代码语言:javascript
复制
app.controller('MainCtrl', function($scope, modal, service) {
  $scope.click = function() {
    modal.show().then(function(result) {
      if (result === 'ok') {
        service.resetPassword();
      }
    });
  };
});

测试

代码语言:javascript
复制
describe('Testing a controller', function() {
  var $scope, $q,
      ctrl, modalMock, serviceMock;

  beforeEach(function() {
    module('plunker');

    modalMock = jasmine.createSpyObj('modal', ['show']);
    serviceMock = jasmine.createSpyObj('service', ['resetPassword']);

    inject(function($rootScope, $controller, _$q_) {
      $scope = $rootScope.$new();
      $q = _$q_;

      ctrl = $controller('MainCtrl', {
        $scope: $scope,
        modal: modalMock,
        service: serviceMock
      });
    });
  });

  it('should reset the password when the user confirms', function() {
    // Arrange
    var deferred = $q.defer();

    deferred.resolve('ok');
    modalMock.show.and.returnValue(deferred.promise);

    // Act
    $scope.click();
    $scope.$digest(); // Makes Angular resolve the promise

    // Assert
    expect(serviceMock.resetPassword).toHaveBeenCalled();
  });

  it('should not reset the password when the user cancels', function() {
    // Arrange
    var deferred = $q.defer();

    deferred.resolve('cancel');
    modalMock.show.and.returnValue(deferred.promise);

    // Act
    $scope.click();
    $scope.$digest(); // Makes Angular resolve the promise

    // Assert
    expect(serviceMock.resetPassword).not.toHaveBeenCalled();
  });
});

工作柱塞

每个测试中的模拟排列代码可以移动到一个beforeEach部分,这样就不会被复制。我这么做不是为了让事情变得简单。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29528088

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档