0

I am trying to write a unit test for my http request

In my controller, I have something like

     $scope.test1 = function(url) {
         productFactory.getProduct(url)
             .then(function(products){
                 $scope.result = products;
              })
    } 

In my unit factory file

    angular.module('myApp').factory('productFactory', function($http) {
        var factoryObj = {};
        factoryObj.getProduct = function(url) {
            return http.get('/product/' + url)
        }
        return factoryObj
    })

in my unit test, I am not sure how to write the test because url is dynamic

describe('test here', function () {
var testCtrl, scope, httpBackend, mockFactory;

// Initialize the controller and a mock scope
beforeEach(inject(function (_$controller_, _$rootScope_, _$httpBackend_,  _productFactory_) {
    scope = _$rootScope_.$new();
    httpBackend = _$httpBackend_;
    mockFactory = _productFactory_;

    testCtrl = _$controller_('testCtrl', {
        $scope: scope
    });


// the url is dynamic so I am not sure what to write here.

   var url = 12345 <----dynamic product id
   httpBackend.whenGet('/product/' + url).response({'name':'product1'}) 
   var promise = mockFactory.getProduct('/product/' + url);
   promise.then(function (prod) {
       var products = prod;
   });
   $httpBackend.flush();
   expect(products).toBeTruthy();
}));

When I run the test, I got

Error: Unexpected request: GET /product/undefined
Expected GET /product/12345

I am not sure how to write a http request in my case. Can anyone help me about it? Thanks!

1
  • What exactly are you testing, the controller or the productFactory? Commented Feb 10, 2015 at 22:40

1 Answer 1

1

It seems you're wanting to test the productFactory and not the controller. The only test I can see is to ensure that the appropriate HTTP request is made.

describe('productFactory test', function() {
    beforeEach(module('myApp'));

    it('getProduct requests /product/:id', inject(function($httpBackend, productFactory) {
        var id = 123;
        $httpBackend.expectGET('/product/' + id);

        productFactory.getProduct(id);
        $httpBackend.flush();
    }));
});

Also, you have a typo in productFactory.getProduct. It should be $http.get, not http.get.


Say your factory uses a cookie service to fetch the ID. Something like this...

.factory('productFactory', function($http, cookieService) {
    return {
        getProduct: function() {
            return $http.get('/product/' + cookieService.getProductid());
        }
    };
});

You would then test it like this (assuming jasmine v2)...

describe('...', function() {
    var cookieService;

    beforeEach(module('myApp', function($provide) {
        $provide.value('cookieService',
            cookieService = jasmine.createSpyObj('cookieService', ['getProductId']));
    });

    it('...', inject(function($httpBackend, productFactory) {
        cookieService.getProductId.and.returnValue(123);
        $httpBackend.expectGET('/product/123');

        productFactory.getProduct();
        expect(cookieService.getProductId).toHaveBeenCalled();

        $httpBackend.flush();
    }));
});
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Phil! Just wondering what if my getProduct function doesn't take id as a param and get id from a cookie. How would you do it? +1
Basically my problem is that I got Error: Unexpected request: GET /product/undefined because my actual getProduct function doesn't know the id.
Ideally, your factory would use another service to read the value from a cookie (or similar). You would then mock and inject that service in your test. I'll provide an example

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.