Unit Testing Service with $rootScope.$broadcast and $timeout

2,117 views
Skip to first unread message

James Morgan

unread,
Mar 1, 2013, 5:38:26 AM3/1/13
to ang...@googlegroups.com
Hi all, I've been trying to unit test a service we created which does the following:

Invoking the service like this: MyService.myMethod

1) Makes a http GET request
2) On success we use $rootScope.$broadcast to broadcast the event to other controllers/directives which may be using it
3) Sets a $timeout(myMethod, minutesInMills(5)) to refresh the data in a set time period, the method invocation is the actual service method its self i.e. MyService.myMethod.

I have been really struggling with creating a unit test for this, so far I can test the GET request like this and it does what I expect

        httpMock.when('GET','/secure/service/data.form').respond(expectedData)
        MyService.myMethod()
        httpMock.flush()

After this point I am stuck, how do I assert/expect the broadcast event with its contents and how would I assert/expect the timeout call?

I have tried the following

        # Setup spy on object and method
        spyOn($rootScopeMock, '$broadcast')
       
        ## Expect the call to be made with given args
        expect($rootScopeMock.$broadcast).toHaveBeenCalledWith('myEvent, myData)

I'm new to Jasmine and come from a JMock/Junit testing background which I why I may be getting confused?

Any help would be greatly appreciated.


James Morgan

unread,
Mar 1, 2013, 7:52:10 AM3/1/13
to ang...@googlegroups.com
I have got this working now after chaining my callback timeout function to not call itself but to call another referenced function, similar to this: http://jsfiddle.net/robinroestenburg/aDwva/

My Jasmine tests looks like this: (CoffeeScript)

    it("Should deal with sucsessful Agent Stats Lookup", inject((MyService) =>
        # Check Service created
        expect(MyService).toBeDefined()
       
        # Expected Assessor Stats
        expectedStats = {stats: {data:"123"} }
       
        # Expected Call To HTTP Service
        @httpMock.when('GET','/secure/assessment/stats.form').respond(expectedStats)
       
        # Run the test!
        MyService.loadStats()

        # Force the polling function through timeout
        @timeoutMock.flush()
       
        # Flush the expected HTTP request
        @httpMock.flush()
   
        # Expected Broadcast to fire with contents of stats
        expect(@rootScope.$broadcast).toHaveBeenCalledWith('onDownloaded', { stats: expectedStats } );

        # Check logs contain expected values
        expect(@logMock.info.logs[0]).toContain("Downloading Stats")
        expect(@logMock.error.logs.length).toEqual(0)
    ))

My final questions regarding this is why the test still passes even if I don't have the expected call from my spied $broadcast, it fails if I pass invalid args to the expected but if I don't have it at all I thought it should fail?

        expect(@rootScope.$broadcast).toHaveBeenCalledWith('onDownloaded', { stats: expectedStats } );

James
Reply all
Reply to author
Forward
0 new messages