Angular/Jasmine:监视传递给 $rootScope.$on 的方法,使用和不使用匿名函数包装器

Angular/Jasmine: spying on method passed to $rootScope.$on with and without anonymous function wrapper

在 angular 中,我在触发 $rootScope.$on 侦听的事件时调用方法。

$rootScope.$on('someEvent', some.method);

我正在监视我的 jasmine 测试中的方法,从我的测试中触发事件,然后检查是否调用了该方法。

spyOn(some, 'method');
$rootScope.$broadcast('someEvent');
expect(some.method).toHaveBeenCalled(); // fails

这个测试失败了。此外,该方法实际上被调用(通过控制台日志验证)。

现在,我可以像这样将方法包装在匿名函数中:

$rootScope.$on('someEvent', function () { some.method(); });

测试通过。

spyOn(some, 'method');
$rootScope.$broadcast('someEvent');
expect(some.method).toHaveBeenCalled(); // passes

在这种情况下,实际上并没有调用方法本身(如预期的那样,因为它正在被监视)。

我已经设置了一套测试来充分说明这个 Plunk:http://plnkr.co/edit/3S5J47OeCBsL0RASGe5P?p=preview

传递给 $rootScope.$on 的方法在事件触发时被调用,无论它是否包装在匿名函数中。然而,间谍只有在包裹在匿名函数中时才会注册。

在 jasmine 中,是否可以成功监视通过引用传递给 $rootScope.$on 的 angular 函数。如果是这样,如何?如果不是,为什么不呢?

spyOn() 是一个突变器。forked your Plunk 并添加了一些控制台日志。

考虑注册间谍的调用:

spyOn(test, 'bar').andCallThrough();

这将创建一个新的间谍函数,该函数执行间谍工作,然后调用间谍函数。然后将间谍存储在对象上以代替原始功能。在您的 "without anonymous wrapper" 示例中,您注册事件以在注册间谍时调用值为 test.bar 的函数 :

$rootScope.$on('withoutFunctionWrapper', test.bar);

而对于包装器,事件将触发事件发生时 test.bar 设置为 的任何事件 ,在您的情况下是间谍:

$rootScope.$on('withFunctionWrapper', function() {
  test.foo();
});

举例说明:

所以您可以先尝试调用 spyOn(),如果您正在监视的函数可以在调用 $rootScope.$on() 之前可用。否则,您将需要包装器。