Tag Archives: angular $httpBackend

TDD Test AngularJs Service $Http

In my last post I have hardcode the data into the service to let my test pass, now in this post I will change that service to by inject the $http service into my module and let it return httpPromise.

Here is my new movieApi.js file


(function(){
   "use strict";
   
  var app =  angular.module('moviesApi',[]);

    app.factory('moviesApi',function($http, $q){
        var service = {};
        var baseUrl = 'http://www.omdbapi.com/?v=1&';

        function httpPromise (url) {
			var deferred = $q.defer();
			$http.get(url)
				.success(function(data) {
					deferred.resolve(data);
				})
				.error(function(error) {
					deferred.reject(error);
				});
			return deferred.promise;
		}

        service.search = function(query) {
			return httpPromise(baseUrl + 's=' + 
                               encodeURIComponent(query));
		} 
                    
   return service;
 });
})()

Then my unit test fail, that is because now my service return a promise and it has not resolve yet, but my test expect data, for how to solve this issue, angularjs has provide $httpBackend for Fake HTTP backend implementation for unit testing application that use the $http service.

Here is the new test code:

$httpBackend;
beforeEach(module('moviesApi'));
         //angular.mock is under the globe variable, so I have remove it 
         //the beforeEach is jasmine provide if you have multiple test need 
         //the same  set up, it will automatic set for each test, will reduce copy code
         //for name convenienceĀ  I also changed the service's name 
         //to match the module name
        //then in the dependence inject angularjs allow your put the underscore 
        //for your inject service,it will pick it up
	beforeEach(inject(function(_moviesApi_,_$httpBackend_) {
		moviesApi = _moviesApi_;
                $httpBackend = _$httpBackend_;
	}));
    
    it('should return search movies data',function(){
        var response;
        var expectedUrl = 'http://www.omdbapi.com/?v=1&s=star%20wars';
        $httpBackend.when('GET',expectedUrl)
                .respond(200,moviesData); 
        
        moviesApi.search('star wars')
                .then(function(data){
                        response = data;
                });

        //the fake $httpBackend has function flush will resolve the data for you to       //test

        $httpBackend.flush();

        expect(response).toEqual(moviesData);
    });

Tips: as frondend developer also could using this Fake data create a service response, so you do not need waiting for the backend service finished to do your job.

 

Now the test will pass.

Have fun!

Advertisements