【问题标题】:How can I trigger `$on` events in AngularJS Karma unit tests?如何在 AngularJS Karma 单元测试中触发“$on”事件?
【发布时间】:2014-10-23 21:29:34
【问题描述】:

我试图在我$rootScope.broadcast() 一个事件时触发的控制器中触发$scope.$on() 方法。我发现这个问题很有用:How can I test events in angular?,但我仍然无法检测到从 $rootScope 向上通过控制器的 $scope 广播的事件。

到目前为止,我已经成功测试了 $broadcast 方法是在相应的 $rootScope 上调用的,但不是 $on 方法是在相应的 $scope 上调用时在 $broadcast 上调用的$rootScope.

我试图在我的测试中直接$rootScope.$broadcast,但我的间谍没有接听该事件。

这是我的控制器:

angular.module('app.admin.controllers.notes', [])
    .controller('NotesCtrl', function($scope) {

      $scope.$on('resource-loaded', function(event, resource) { // I want to test this
        $scope.parentType = resource.type;
        $scope.parentId = resource.id;
      });

    });

这是我的测试:

describe('The notes controller', function() {

  beforeEach(module('app.admin.controllers.notes'));

  var scope, rootScope, NotesCtrl;

  beforeEach(inject(function($controller, $injector, $rootScope) {
    rootScope = $rootScope;
    scope = $rootScope.$new(); // I've tried this with and without $new()
    NotesCtrl = $controller('NotesCtrl', {$scope: scope}); // I've tried explicitly defining $rootScope here
  }));

  it('should respond to the `resource-loaded` event', function() {
    spyOn(scope, '$on');
    rootScope.$broadcast('resource-loaded'); // This is what I expect to trigger the `$on` method
    expect(scope.$on).toHaveBeenCalled();
  });

});

还有here's the plunkr。我已经包含了$broadcast 方法的通过测试以供参考,主要是因为我以相同的方式设置测试。

我已经阅读了很多与 AngularJS 中的测试事件相关的问题,这似乎总是一个范围界定问题。我听说在 Karma 单元测试中,$rootScope$scope 是一回事,但我不太确定这意味着什么。我尝试将$rootScope$scope 定义为同一个对象,并在测试期间将$rootScope 显式注入NotesCtrl,但没有什么能让我的测试变绿。

如何让我的NotesCtrl 中的$on 方法为该测试触发?

【问题讨论】:

    标签: angularjs unit-testing karma-runner


    【解决方案1】:

    导致它不起作用的原因是您正在监视$on 函数。不说它时它工作正常:http://plnkr.co/edit/hNEj7MmDDKJcJ7b298OB?p=info。而原因其实很简单。广播事件时,调用的不是$on()函数。调用的是之前作为参数传递给$on()的回调函数:监听器。

    请注意,通过监视 $on 函数,您不是在此处测试您的代码。您要测试的只是在广播事件时,子作用域会接收它。因此,您正在测试 AngularJS 本身。

    【讨论】:

    • 这确实有点晚了,但是为了以后发现这个的人参考,你可以在创建间谍时添加 .and.callThrough() 来测试这种情况。
    【解决方案2】:

    尝试使用

    $rootScope.$emit('resource-loaded');
    

    在我的测试中运行良好。

    【讨论】:

    • $emit 将消息向上发送到作用域树; $broadcast 挂了。
    【解决方案3】:

    @kirill.buga

    使用 $broadcast 是对的,而不是 $emit 因为:

    https://docs.angularjs.org/api/ng/type/$rootScope.Scope 通过范围层次结构向上调度事件名称,通知已注册的 $rootScope.Scope 侦听器。

    @ben-harold 的问题是试图窥探 $on 而不是 $on 中代码的结果。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-17
      • 2013-08-02
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      • 1970-01-01
      • 2015-11-29
      • 1970-01-01
      相关资源
      最近更新 更多