Jasmine + AngularJS:如何测试$ rootScope.使用参数调用$ broadcast?

And*_*rea 8 javascript jasmine angularjs karma-jasmine yeoman-generator-angular

我正在尝试编写一个单元测试来验证$rootScope.$broadcast('myApiPlay', { action : 'play' });被调用.

这是myapi.js

angular.module('myApp').factory('MyApi', function ($rootScope) {
    var api = {};
    api.play = function() {
        $rootScope.$broadcast('myApiPlay', { action : 'play' });
    }
    return api;
});
Run Code Online (Sandbox Code Playgroud)

这是我的单元测试:

describe('Service: MyApi', function () {

    // load the service's module
    beforeEach(module('myApp'));

    // instantiate service
    var MyApi;
    var rootScope;

    beforeEach(function () {
        inject(function ($rootScope, _MyApi_) {
            MyApi = _MyApi_;
            rootScope = $rootScope.$new();
        })
    });
    it('should broadcast to play', function () {
        spyOn(rootScope, '$broadcast').andCallThrough();
        rootScope.$on('myApiPlay', function (event, data) {
            expect(data.action).toBe('play');
        });
        MyApi.play();
        expect(rootScope.$broadcast).toHaveBeenCalledWith('myApiPlay');
    });
});
Run Code Online (Sandbox Code Playgroud)

这是我在运行时遇到的错误grunt test:

PhantomJS 1.9.7 (Windows 7) Service: MyApi should broadcast to pause FAILED
        Expected spy $broadcast to have been called with [ 'myApiPlay' ] but it was never called.
Run Code Online (Sandbox Code Playgroud)

我也尝试过expect(rootScope.$broadcast).toHaveBeenCalled(),我遇到了类似的错误:Expected spy $broadcast to have been called..

我想验证是否已使用正确的参数调用该方法.

谢谢!

jcr*_*ruz 14

你的测试没有通过的原因是因为你正在监视错误的$ broadcast功能.在beforeEach设置中,您要求注入$ rootScope,然后通过调用$ rootScope来创建子范围.$ new().

$ rootScope.$ new()的返回值不再是rootScope,而是根范围的子节点.

beforeEach(function () {
    //inject $rootScope
    inject(function ($rootScope, _MyApi_) {
        MyApi = _MyApi_;
        //create a new child scope and call it root scope
        rootScope = $rootScope.$new();
        //instead don't create a child scope and keep a reference to the actual rootScope
        rootScope = $rootScope;
    })
});
Run Code Online (Sandbox Code Playgroud)

在你的游戏功能中,你在$ rootScope上调用$ broadcast,但在你的测试中你正在监视$ rootScope的孩子.

$rootScope.$broadcast('myApiPlay', { action : 'play' });
Run Code Online (Sandbox Code Playgroud)

所以要把它包起来,删除对$ rootScope.$ new()的调用,然后只调查注入器给你的$ rootScope.提供给您的单元测试的$ rootScope与提供给您的API服务的$ rootScope相同,因此您应该直接在$ rootScope上进行间谍活动.

查看plunkr http://plnkr.co/edit/wN0m8no2FlKf3BZKjC4k?p=preview

  • 这对于`期望(rootScope.$ broadcast).toHaveBeenCalledWith('myApiPlay',{action:'play'});`但这个期望不会被调用:`rootScope.$ on('myApiPlay',function(event, data){expect(data.action).toBe('play');});` (2认同)