Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS testing: Mocking $httpBackend - Handling Success and Error Methods

Update: I managed to further narrow down the problem scope and fix the Unexpected request error by updating the httpBackend.when request which contained some invalid ascii characters.

I have attached a Plunker witht he current code block.

But I am still having difficulty in effectively testing the triggering of success and error method operations.I also need to add expectations to check message broadcasting.

In order to test the above mentioned scenario I devised an hack which I have included in Plunker but I believe there should be a much better way to test these scenarios.

Any leads on how I can overcome this problem and test the response message status would be much appreciated.

Problem

I've set the expected value/response for $httpBackend for my test, but when I run $httpBackend.flush(), it fails indicating the below mention error.

Error message indicated

Error: Unexpected request: GET https://192.168.1.10:3334/res?t1=CHECK&t2='?'&req={"_msgType":"Login_msg","UserName":"[email protected]","Password":"123"}

I did find some useful links that discussed about this problem domain and they did help me somewhat to narrow down the problem scope. But I still can't seems to figure out the specific reason why this unit test fails.

Useful Stack Overflow Questions

  • Angular mock $httpBackend give No pending request to flush
  • Unit testing AngularJS with $httpBackend gives “Error: Unexpected Request”
  • Testing Angular $resource with external service
  • Why do I receive error … unexpected request
  • Mocking $httpBackend

Useful external resources

  • AngularJS Tests With An HTTP Mock
  • Unit Testing $http service in Angular.js
  • Angularjs Tutorial: Testing using ngMock $httpBackend and karma.
  • Angular JS - Unit Testing - Services
  • AngularJS Tests With An HTTP Mock

I also tried moving the flush() call around and also tried calling $apply or $digest when making a $http requests fire in a test as suggested here.

AngularJS Service to be tested

    app.service('restService',['$log','$http','$rootScope',function($log,$http,$rootScope)
{
    this.location = null;
    this.port = null;

    this.sendRequest = function(host,port,param1,param2,requestMsg)
    {
        this.location = host;
        this.port = port;
        $http.get('https://'+host+":"+port+"/res?t1="+param1+"&t2="+param2+"&req="+JSON.stringify(requestMsg)).
        success(function(data) { 
           //Need to add expectations to check success operations
           $log.log('response received',data);
           var msgData  = data;
           $rootScope.successCalled = true;
           $rootScope.response = data;
            if(msgData.hasOwnProperty('_msgType'))
            {
                $log.log('broadcast for channel',msgData._msgType);
                $rootScope.$broadcast(msgData._msgType,msgData);
            }
        }).
        error(function(){
            //Need to add expectations to check error method operations
            var httpErrMsg = {_msgType:'HTTPErr', host:host, port:port, t1:param1, t2:param2, requestMsg:requestMsg};
            $rootScope.errorCalled = true;
            $rootScope.response = data;
            $rootScope.$broadcast(httpErrMsg._msgType,httpErrMsg);
        });
    }

    this.getIP = function()
    {
        return this.location;
    }
    this.getPort = function()
    {
        return this.port;
    }
}])

Specs used to test Service

     "use strict";                                   

    describe("Rest service test", function() 
    {
        var $scope, $location, httpBackend, $log, restService , loginMsg ;

        beforeEach(module('app'));

    beforeEach(inject(function (_restService_) 
    {
    restService = _restService_;
    }));

    beforeEach(inject(function($rootScope, _$location_, $httpBackend, _$log_)
    {
        $scope    =  $rootScope.$new();
        $location = _$location_;
        httpBackend = $httpBackend;
        $log = _$log_;

        loginMsg={ _msgType:"Login_msg", UserName:"[email protected]", Password:"123"};
    }));

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

    describe("Service : Rest Service", function()
    {
      it('Should start with location and port undefined', function() {
      expect(restService.location).toEqual(null);
      expect(restService.port).toEqual(null);
      });

      it("check if method exists", function() {
      expect(restService.sendRequest).toBeDefined();
      });

      it("GetIP method Exists ", function()
      {
       expect(restService.getIP).toBeDefined();
      });

      it("GetPort method Exists ", function()
      {
      expect(restService.getPort).toBeDefined();
      });

      it("GetIP  Value ", function()
      {
      restService.location = '192.168.1.10';
      expect(restService.location).toEqual('192.168.1.10');
      });

      it("GetPort Value ", function()
      {
      restService.port = '3334';
      expect(restService.port).toEqual('3334');
      });

      it("Execute sendRequest()", function() {
      httpBackend.when('GET', 'https://192.168.1.10:3334/res?t1=CHECK&t2=\'?\'&req={"_msgType":"Login_msg","UserName":"[email protected]","Password":"123"}')
      .respond ({SessionId:"2103337586",Status:"user [email protected] not found ",EMail:"[email protected]",rejectCode:1,rejectReason:"Invalid username or password",_msgType:"LoginReply_msg"});
      restService.sendRequest("192.168.1.10","3334","CHECK","'?'",loginMsg);
      httpBackend.flush();

      expect(restService.location).toEqual('192.168.1.10');
      expect(restService.port).toEqual('3334');
      expect($scope.successCalled).toBe(true);
      expect($scope.response).not.toBe(null);
      expect($scope.response._msgType).toEqual('LoginReply_msg');
      });
   });
});
like image 710
Gehan Avatar asked Nov 10 '22 02:11

Gehan


1 Answers

I know, this question is old, but maybe someone is looking for, this could be helpful.

modify your beforeEach function like this:

beforeEach(inject(function($rootScope, _$location_, $httpBackend, _$log_)
{
    $scope    =  $rootScope.$new();
    $location = _$location_;
    httpBackend = $httpBackend;
    $log = _$log_;

    loginMsg={ _msgType:"Login_msg", UserName:"[email protected]", Password:"123"};

    httpBackend.expectGET(/192.168.1.10:3334/i).respond(function (){
        return [/*mockResponse*/];
    });
}));

this will resolve this error.

like image 84
Anke Wenz Avatar answered Nov 15 '22 10:11

Anke Wenz