Jasmine(通过 TypeScript)测试以验证范围 $on 被调用

Posted

技术标签:

【中文标题】Jasmine(通过 TypeScript)测试以验证范围 $on 被调用【英文标题】:Jasmine (via TypeScript) test to verify scope $on is called 【发布时间】:2016-04-21 15:43:45 【问题描述】:

我搜索了几个地方来获得这方面的想法。

How do I unit test $scope.broadcast, $scope.$on using Jasmine

$scope.$on not working in Jasmine SpecRunner

这有助于我思考,但似乎我仍然缺少一些东西。我正在尝试测试代码中有 $rootScope.$on 的控制器。所以在单元测试中我试图触发 $broadcast 以便 $on 得到它并且代码运行。但是我当前的代码不起作用。

这是我的控制器:

constructor($state: ng.ui.IStateService, store: angular.a0.storage.IStoreService, jwtHelper: angular.jwt.IJwtHelper, $rootScope: any) 
    this.currentDate = new Date();
    this.state = $state;
    this.store = store;
    this.jwtHelper = jwtHelper;
    this.userFullname = '';

    $rootScope.$on('$stateChangeStart',
        (event: any, toState: any, toParams: any, fromState: any, fromParams: any, error: any) => 
            var jwtToken = this.store.get('token');
            if (jwtToken != null) 
                var decodedToken: any = this.jwtHelper.decodeToken(jwtToken);
                 
        );


这是我的测试:

 beforeEach(angular.mock.inject(($compile: ng.ICompileService, $rootScope: any, $controller: any, $state: ng.ui.IStateService, jwtHelper: angular.jwt.IJwtHelper) => 

    controllerScope = $rootScope.$new();
    navbarController = $controller('NavbarController',  $scope: controllerScope );
    currentDate = new Date();
    rootScope = $rootScope;
    state = $state;
    jwt = jwtHelper;


it('should get broadcast for user token', () => 
    spyOn(controllerScope, '$on');
    spyOn(jwt, 'decodeToken');
    //state.go('home'); Was trying a different way to trigger the event
    rootScope.$broadcast('$stateChangeStart', [ toState: 'home' ]);
    expect(controllerScope.$on).toHaveBeenCalled();
    expect(jwt.decodeToken).toHaveBeenCalled();
);

两个间谍都说他们从未被召唤。我错过了什么?

【问题讨论】:

【参考方案1】:

如果您想测试事件是否被广播,请执行spyOn(scope, '$broadcast').and.callThrough();

如果您想测试控制器的逻辑,请将其包装在一个函数中,并与$broadcast / $on 分开测试(毕竟您不是在测试 Angular 的事件传递机制)。

【讨论】:

我想测试一下 1) 控制器正在监听事件 2) 当事件发生时,定义的函数正确执行。你有答案或方法吗?【参考方案2】:

您不是测试事件 listener 是否被触发,而是验证 注册侦听器的代码是否被触发。

它被触发了,但是controllerScope.$on 在你的beforeEach 函数中被调用,而不是在你的it 中。 spyOn 无法进入过去以检测先前的函数调用;即使是这样,那也可能不是您要进行的测试。

基本上你已经做了这样的事情:

window.addEventListener('mouseMove', someFunctionExpr);
spyOn(window, 'addEventListener');
triggerMouseMoveEvent();
expect(window.addEventListener).toHaveBeenCalled();

我无法与decodeToken / jwt 通话——您的代码在任何地方都没有引用它,所以我不知道应该在哪里调用它。

【讨论】:

谢谢。我更新了我的代码以显示 jwt 调用发生的位置。它发生在 $on 注册的函数内部。这就是为什么我也添加了那个间谍,但它也说它没有被解雇。 只是为了提供有关我问题根源的更新。 1)根据瑞安所说,“$on”被提前解雇以进行监视。它正在射击,但无法捕捉到它。 2)我有另一个 jwtHelper 方法,我需要在我正在观看的间谍之前进行间谍和伪造,并且之前的方法阻止了我正在观看的方法,因此它没有被调用。一旦我得到了一致,一切都很好。对其进行了调整以测试我的功能而不是事件路由。

以上是关于Jasmine(通过 TypeScript)测试以验证范围 $on 被调用的主要内容,如果未能解决你的问题,请参考以下文章

如何测试使用 jasmine + TypeScript 使用常量调用的函数

使用 Jasmine 和 TypeScript 进行单元测试

Chutzpah - 使用 jasmine 和 TypeScript 进行 AngularJS 测试

单元测试 typescript 指令模板 karma-jasmine,html 未定义

在 vs 代码中调试用 typescript 节点编写的 jasmine 测试

typescript Angular 2+ Jasmine测试规格样板