2

I will just start out saying that $httpBackend and spyOn are pretty new to me, and I am struggling to get a clear picture of what is happening. Basically, I'm trying to do an $httpBackend.expectGET('/myroute/').respond(...) and then use spyOn, but I keep getting

Expected [  ] to equal Object({ success: true, message: 'Yeah!' })

Here's the code I'm trying to test:

angular.module('TestModule')
       .service('TestService',TestService);

TestService.$inject = ['$http'];
function TestService($http){
    var service = {};
    service.DoIt = DoIt;
    return service;

    function DoIt() {
        return $http.get('/myroute/')
            .then(handleSuccess,handleError('Error happened!'));
    }

    function handleSuccess(res) {
        return res.data;
    }

    function handleError(error) {
        return function(){
            return {success: false, message: error}
        };
    }
}

Here's my Karma-Jasmine test:

describe('Test Module',function(){
    beforeEach(module('TestModule'));

    describe('TestService Tests',function(){
        var service,$httpBackend;
        beforeEach(inject([
             '$injector',
             function($injector){
                 $httpBackend = $injector.get('$httpBackend');
                 service = $injector.get('TestService');
             }
        ]));

        afterEach(function(){
            $httpBackend.verifyNoOutstandingExpectation();
            $httpBackend.verifyNoOutstandingRequest();
        });

        it('should DoIt',function(){
            var mockResponse = {
                data : {success:true, message:"Yeah!"}
            };

            $httpBackend.expectGET('/myroute')
                        .respond(Promise.resolve(mockResponse));

            spyOn(service,'DoIt').and.callThrough();

            service.DoIt().then(function(data){
                expect(service.DoIt).toHaveBeenCalled();
                expect(data).toEqual(mockResponse.data); <-- ERROR OCCURS HERE -->
            });

            $httpBackend.flush();
        });

    });
});

Further information:

Using the example I found here: http://www.bradoncode.com/blog/2015/06/26/unit-testing-http-ngmock-fundamentals/, I tried this in my test code:

it('should DoIt',inject(function($http){
    var promise = $http.get('/myroute').then(handleSuccess,handleError('bad stuff happened'));
    promise.then(function(data){
        console.log('Data: ' + JSON.stringify(data,null,3));
    });

    $httpBackend.expect('GET','/myroute').respond(200,{data:'Yeah!'});
    $httpBackend.flush();
}));

function handleSuccess(response) {return response.data;}
function handleError(error){
    return function(){
        return {success:false,message:error};
    };
}

This gives me the response that I expect: 'Data: {"data": "yeah"}'

My updated question: I thought service.DoIt() was doing the same thing as the promise. What is going on here? Am I not injecting my service? I do not understand how Karma expects me to stage this test. Any help, please!

westandy
  • 1,360
  • 2
  • 16
  • 41
  • @jbrown - I guess this is where the syntax gets me. I thought I was passing it in. I thought my $httpBackend.expectGET('/myroute').respond(...) was taking care of the $http.get('/myroute') in DoIt(). I thought my mockResponse would then be passed to handleSuccess() and it had a 'data' property. But that's not what is happening here? – westandy Jun 01 '16 at 20:35
  • That just sets 'data' to undefined. – westandy Jun 01 '16 at 21:10
  • Also, since you brought it up, what problems are you seeing with the service code? Thanks for any input. – westandy Jun 01 '16 at 21:22

2 Answers2

2

If I understand your intention with the test correctly, I believe this is what you need:

describe('Test Module', function() {

    var $httpBackend, service;

    beforeEach(module('TestService'));

    beforeEach(inject(function(_$httpBackend_, _TestService_) {
        $httpBackend = _$httpBackend_;
        service = _TestService_;
    }));

    afterEach(function() {
        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    });

    it('should DoIt', function() {
        var mockResponse = {
            data: { success: true, message: "Yeah!" }
        };

        $httpBackend.expectGET('/myroute/')
            .respond(mockResponse);

        service.DoIt().then(function(data) {
            expect(data).toEqual(mockResponse);
        });

        $httpBackend.flush();
    });

});
Bradley Braithwaite
  • 1,122
  • 2
  • 19
  • 22
  • This gives me "Expected [ ] to equal Object({ data: Object({ success: true, message: 'Yeah!' }) })", which is the same error I was getting before. Basically, this "solution" changes the injection syntax. According to Angular's API, both of our injection syntax's are legitimate. – westandy Jun 01 '16 at 22:55
  • Basically, this "solution" passes on my machine using the code you pasted for your service. – Bradley Braithwaite Jun 01 '16 at 23:03
  • It also fixes a typo in the route for your $httpBackend.expectGET – Bradley Braithwaite Jun 01 '16 at 23:03
  • Then maybe I've got my karma.conf setup wrong? What could be the difference, then? I can add it if you think it might help. – westandy Jun 01 '16 at 23:04
  • OK, holy crap. I've got my angular.module('TestModule').service('TestService',...) wrapped in a (function(){'use strict'; angular... })();. When I stripped off that function(),use strict wrapper, it worked like you said. I didn't think that would affect karma-jasmine like that. – westandy Jun 01 '16 at 23:09
  • I'm just losing my mind. I must not have hit CTRL-S, or something. Regardless, your solution works. Sorry for not paying close enough attention. Thank you! – westandy Jun 01 '16 at 23:23
  • Yeah, don't get hung up on the different injector style, I just wrote a test very quickly from scratch and copy/pasted. The code within the `it` function is where the magic is... – Bradley Braithwaite Jun 02 '16 at 12:29
0

In my case there was transformResponse function on $resource that modified the expected mock data:

var resource = $resource('api/data/:id', {}, { get: { method: 'GET', isArray: true, transformResponse: function (data) { var d = angular.fromJson(data); return d.members; } } ...

My mock data didn't contain memebers...

Felix
  • 3,999
  • 3
  • 42
  • 66