How to write unit test for http request?

I am trying to do a unit test service in my case

In my test controller

myService.getItem('/api/toy/' + scope.id).success( function(toy) { $scope.toy = toys.details; } ); 

MyService

 angular.module('toyApp').service('myService', ['$http', function($http) { var service = {}; return { getItem: function(url) { return $http.get(url); }, }; } ]); 

Test file.

 describe('toy ctrl', function () { var $httpBackend, ctrl, myService; beforeEach(module('toyApp')); beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_, __myService_) { scope = _$rootScope_.$new(); $httpBackend = _$httpBackend_; myService = _myService_; ctrl = _$controller_('toyCtrl', { $scope: scope }); })); describe('call my service', function() { it('should make request when app loads', function() { $httpBackend.expectGET('/api/toy/123').respond({id:123, detail:456 }); myService.getItem('/api/toy/123').then(function(toy){ expect(scope.toy.detail).toBe(456); }) $httpBackend.flush(); }) }) 

I get

 Error: Unexpected request: GET /api/toy/123 No more request expected 

If you take out $httpBackend.flush() , the error will disappear, but it will not close

  function(toy) { $scope.toy = toys.details; } 

part. I want to cover a function call and don’t know how to do it. Can anyone help me? Thank you very much

+6
source share
1 answer

It seems that you are the "unit" checking the controller, so you do not need to enter the service in the picture, since you just need to check the logic of the controller. You can create a service layout and enter it during the creation of the controller in your test.

Example:

 var mockItem = {details:{//somestuff}, id:'1'};// set up a mock object to test against later //.... beforeEach(inject(function (_$controller_, _$httpBackend_, _$rootScope_, _$q_) { scope = _$rootScope_.$new(); $httpBackend = _$httpBackend_; //Set up mock myService = jasmine.CreateSpyObj('myService', ['getItem']); myService.getItem.and.returnValue($q.when(mockItem )); ctrl = _$controller_('toyCtrl', { $scope: scope, myService: myService //<-- Pass it here }); })); //.....Assuming you are making the call when controller is instantiated it('should make request when app loads', function() { expect(myService.getItem).toHaveBeenCalled(); //You could also check as below //expect(myService.getItem).toHaveBeenCalledWith(expectedidpassedin); scope.$digest(); //Resolve $q promise callback expect($scope.toy).toEqual(mockItem .details); }); 

If you specifically test your service, you can:

 it('should make request when app loads', function() { var resp; $httpBackend.expectGET('/api/toy/123').respond({id:123, detail:456}); myService.getItem('/api/toy/123').then(function(response){ resp = response.data; }); $httpBackend.flush(); expect(resp.detail).toEqual(456); }); 

In your controller, instead of success chain use then

  myService.getItem('/api/toy/' + scope.id).then( function(response) { $scope.toy = response.toys.details; }); 
+3
source

Source: https://habr.com/ru/post/987435/


All Articles