最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Jasmine + AngularJS: How to test $rootScope.$broadcast being called with arguments? - Stack Overflow

programmeradmin1浏览0评论

I am trying to write a unit test that verifies that $rootScope.$broadcast('myApiPlay', { action : 'play' }); is called.

Here is the myapi.js

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

And here is my Unit Test:

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');
    });
});

Here is the error i'm getting while running 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.

I have also tried with expect(rootScope.$broadcast).toHaveBeenCalled() and I am having a similar error: Expected spy $broadcast to have been called..

I would like to verify that that method has actually been called with the right parameters.

Thank you!

I am trying to write a unit test that verifies that $rootScope.$broadcast('myApiPlay', { action : 'play' }); is called.

Here is the myapi.js

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

And here is my Unit Test:

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');
    });
});

Here is the error i'm getting while running 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.

I have also tried with expect(rootScope.$broadcast).toHaveBeenCalled() and I am having a similar error: Expected spy $broadcast to have been called..

I would like to verify that that method has actually been called with the right parameters.

Thank you!

Share Improve this question edited Sep 12, 2014 at 22:42 Andrea asked Sep 12, 2014 at 22:04 AndreaAndrea 1551 gold badge1 silver badge9 bronze badges 2
  • Do you just need to switch the order? You might need to expect before it's actually called, in your case you call it, then expect it. You could also confirm that call count. – hassassin Commented Sep 12, 2014 at 22:12
  • I switched the order, same error. – Andrea Commented Sep 12, 2014 at 22:25
Add a comment  | 

2 Answers 2

Reset to default 15

The reason your tests are not passing is because you are spying on the wrong $broadcast function. In your beforeEach setup, you ask to have the $rootScope injected and then you create a child scope by calling $rootScope.$new().

The return value from $rootScope.$new() is no longer the rootScope but a child of the root scope.

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;
    })
});

In your play function, you are calling $broadcast on the $rootScope but in your test you are spying on a child of $rootScope.

$rootScope.$broadcast('myApiPlay', { action : 'play' });

So to wrap it up, remove the call to $rootScope.$new() and just spy on the $rootScope the injector has given you. The $rootScope provided to your unit test is the same $rootScope provided to your API service so you should be spying directly on the $rootScope.

Check out the plunkr http://plnkr.co/edit/wN0m8no2FlKf3BZKjC4k?p=preview

It will be helpful for you https://stackoverflow.com/a/17227264/2594499 Your test isn't clear. Avoid using "expect" in conditions, callbacks and things like this. If your condition won't be true, you've got test without assertion.

It'll be better to use second parameter of function:

.toHaveBeenCalledwith('someEvent', someObj);
发布评论

评论列表(0)

  1. 暂无评论