Unit testing promises attached to AngularJS scope

One of the many bits of magic AngularJS makes an automatic promise for you so that you can write code like this:

function SomeCtrl($scope, Resource) {
    $scope.items = Resource.query();
}

      

However, the service I'm working with functions with via JSON-RPC and ngResource doesn't seem to play well with it. I had to mock the backend to respond appropriately, but for some reason I can't figure out how to validate the response at the controller level.

"use strict";

describe('controllers', function() {

    describe('LibraryCtrl', function() {
        var scope, ctrl;

        beforeEach(inject(function($rootScope, $controller) {

            JsonRpc.respondWith({ some : data });

            scope = $rootScope.$new();
            ctrl = $controller(LibraryCtrl, { $scope : scope }); 
            // controller does `$scope.items = RPCService.get()`
        }));

        it("should create a `items` model with data fetched via JSON-RPC", function() {
            // here where I'm very confused
            // JsonRpc does $httpBackend.flush()
            JsonRpc.respond();

            // now I want to inspect the property on the controller
            expect(scope.items).toEqualData( { some : data } );
        }); 
    }); 

});

      

The problem is what scope.items

the promise is. This particular property will remain a promise because it $digest()

does not appear to resolve the promise and does not attach the return value as a model value. I cannot make a simple equality statement.

My workaround is to use a promise layout:

var result = {
    capture : function(v) { result.value = v; },
    value   : null,
};

      

and then try this:

scope.items.then(result.capture);
expect(result.value).toEqualData(...);

      

It works (but somehow wrong). As a by-product (not a real question for brown dots), replacing the string result.capture

with JsonRpc.respond()

causes the test to fail ( result.value

being null).

Here are the questions: what is the correct way to test promises as model models? Is this result the result. What am I doing ok, or is there a better way to do this? Also, I would love to know why reversing the binding of promises with a reaction flush results in the response not resolving or capturing ...?

+3


source to share


1 answer


Good question. My first reaction is that your controller unit test is actually testing the ngResource here. In my controller tests, I wrap the resource:
mockResource = {query: jasmine.createSpy('query').andReturn([{id: 1, name: foo}])

module(function ($provide) {
   $provide.value('Resource', mockResource);

...

expect(mockResource.find).toHaveBeenCalled()
expect(scope.items)....

      



This allows you to isolate the controller.

+2


source







All Articles