【问题标题】:Why am I losing my invocation context when testing code inside of a promise (angular + jasmine)为什么在 Promise (angular + jasmine) 中测试代码时我会丢失调用上下文
【发布时间】:2016-05-03 18:41:49
【问题描述】:

我有一个简单的控制器,我想在其中测试 promise 内部的机制(在这种情况下,我想测试在运行 bar 时调用了 foo。这是我的控制器:

angular.module('myModule', [])
  .controller('MyCtrl', function ($q) {

  var myPromise = $q.when();

  this.foo = function () {
    console.log('running foo');
  };

  this.bar = function () {
    myPromise.then(function () {
      this.foo();
    });
  };
});

这是我的茉莉花测试:

describe('MyCtrl', function () {
  var $controller, $scope, $q;

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

  describe('bar function', function () {
    it('should call the foo function', function () {
      var controller = $controller('MyCtrl', { $q: $q });
      spyOn(controller, 'foo');
      controller.bar();
      $scope.$digest();
      expect(controller.foo).toHaveBeenCalled();
    });
  });
});

当我运行这个测试时,我得到这个错误:

TypeError: 'undefined' is not an object (evaluating 'this.foo')

似乎在then() 功能块内,我失去了引用控制器的调用上下文。当测试运行并命中this.foo() 时,this 未定义。

【问题讨论】:

  • 不确定这是否是问题所在,但可能存在范围问题。尝试在控制器顶部添加var self = this,然后将this.bar() 函数内部对this.foo() 的引用更改为self.foo()。让我知道这是否有效。

标签: angularjs jasmine promise q angular-mock


【解决方案1】:

'this' 不包含属性'foo',因为上下文(到外部范围)未绑定。

您可以执行以下操作之一:

1.

this.bar = function() {
    var that = this;
    myPromise.then(function () {
        that.foo();
    });
};

2.

this.bar = function() {
    function onSuccess() { this.foo(); }
    myPromise.then(onSuccess.bind(this));
};

【讨论】:

  • 另外,如果你能够使用 es6 语法,你可以使用箭头函数来保留外部上下文中的 thismyPromise.then(() => this.foo());.
  • 绑定到外部范围就是答案。我的示例的最终代码如下所示: myPromise.then(function () { this.foo(); }.bind(this));
猜你喜欢
  • 1970-01-01
  • 2013-11-12
  • 1970-01-01
  • 2018-10-25
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-28
相关资源
最近更新 更多