如何在Angular中测试事件?

67
我需要测试事件是否正确发射或广播,并手动触发事件。这该怎么做?
3个回答

120

如果您只需要对事件触发和捕获进行测试,那么这就是我所做的。要确保某个事件被触发(通过 $emit$broadcast),则可以使用 spy 。您需要引用将调用 $emit$broadcast 的作用域,然后只需像这样做:

spyOn(scope, "$emit")
//run code to test
expect(scope.$emit).toHaveBeenCalledWith("MY_EVENT_ID", other, possible, args);

如果您不需要或不想担心通过$emit传递的参数,您可以在$rootScope上放置一个$on并设置一个标志以了解事件是否已经被发出。像这样:

var eventEmitted = false;
$rootScope.$on("MY_EVENT_ID", function() {
   eventEmitted = true;
});
//run code to test
expect(eventEmitted).toBe(true);

当测试在事件被捕获时运行的功能($on)时,这会更容易一些。只需从inject函数获取一个$rootScope,然后发送所需的事件即可。

$rootScope.$broadcast("EVENT_TO_TEST", other, possible, args);
//expects for event here

现在,我想象这个事件处理会发生在指令或控制器(或两者都有)中。要设置指令测试,请参见https://github.com/vojtajina/ng-directive-testing。要设置控制器测试,请参见https://github.com/angular/angular-phonecat/blob/master/test/unit/controllersSpec.js#L27


这对于精确匹配很好,但如何匹配一组参数的子集呢?例如,如果参数只是一个对象 {p1:'yes', p2:'no'},您希望p1:'yes'无论p2是什么(或者是否存在)都能匹配成功吗?我知道有“any” jasmine键盘,但那似乎是相反的——控制不够细致。有没有中间地带可以期望只得到您想要的参数? - Luke Madera
@LukeMadera Jasmine有jasmine.objectContaining。从文档中可以看到:当期望只关心实际对象中的某些键/值对时,jasmine.objectContaining就派上用场了。 - Ricardo Pedroni
谢谢,但有没有一种使用jasmine的方法呢?类似这样:expect(scope.$emit.calls.argsFor(0)[0]).toBe('MY_EVENT_ID'); - Cameron
@dnc253 我有一个父节点监听 $emit 事件。只有当我使用 $rootScope.$broadcast 广播事件并检查事件时,我的测试才能通过,如果使用 $rootScope.$emit,则无法通过测试。这是因为 $emit 只能向上遍历节点而不能向下到子节点吗? - Karthik Balakrishnan
@cameronjroe 有点晚了,但我认为使用 toHaveBeenCalledWith 即使只是检查事件是否被触发也是合适的。这是因为事件名称是 $emit 的一个参数,所以这个测试是有意义的。 - a7omiton

0
我们在A1中使用了这个语法。
=========== Controller ========
    var vm = this;
    $scope.$on('myEvent', function(event, data){
        console.log('event number', data.id);
    });
============ Test =============
 it('should throw myEvent', function() {
    var data = {};
    $scope.$broadcast('myEvent', {id:1});
    $scope.$broadcast('myEvent', {id:2});
    $scope.$broadcast('myEvent', {id:3});
});

============ Output ============
Chrome LOG: '--------------------------------------------'
Chrome LOG: 'event number', 1
Chrome LOG: 'event number', 2
Chrome LOG: 'event number', 3

0

以下是在AngularJS中广播事件的步骤:

在注入时,请按照以下方式初始化rootScope和scope stub:

var rootScope;
var scopeStub = beforeEach(function() {
    inject(function($rootScope, _$controller_) {
        rootScope = $rootScope;
        scopeStub = $rootScope.$new();
        $controller = _$controller_;
    });
});

在创建控制器后,使用rootScope触发事件,如下所示:

rootScope.$broadcast('eventName', parameter1);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接