0

I'm trying to write a unit test using karma and jasmine for an Angular controller that depends on a service

storesController.js

(function () {
var app = angular.module('storesController', ['storesService']);

app.controller('StoresListController', function ($scope, StoresService) {


    $scope.getStores = function () {
        StoresService.getStores().then(function (data) {
            $scope.stores = data.data;
        });
    };
    $scope.getStores();

    $scope.deleteStore = function (id) {
        StoresService.deleteStore(id).then(function () {
            $scope.getStores();
        });

    };
});

storesService.js

(function () {
var app = angular.module('storesService', []);

app.factory('StoresService', ['$http', function ($http) {

        var stores = [];

        stores.getStores = function () {
           return $http.get(/api/getStores');
        };            
        stores.deleteStore = function (storeID) {
            return $http.delete(/api/deleteStore/'+storeID);
        };
        return stores;

    }]);
})();

And the test, controllers.spec.js

describe('StoresController', function () {
    beforeEach(module('storesController'));

    var scope;
    var storesServiceMock;
    var controller;

    beforeEach(inject(function ($controller, $rootScope) {

        storesServiceMock = {
            getStores: function() {
            },
            deleteStores: function() {
            }
       };
       spyOn(storesServiceMock, 'getStores').and.returnValue({name : 'TestName', country : 'TestCountry'}) 

        scope = $rootScope.$new();
        controller = $controller('StoresListController', {
           $scope: scope, StoresService: storesServiceMock
       });
    }));

    it('scope.stores should be defined', function () {
          expect(scope.stores).toBeDefined;
    });
});

And I'm getting

TypeError: StoresService.getStores(...).then is not a function at n.$scope.getStores 

I've also tried width httpBackend but I'm not be able to make it work, any clue about what I'm doing wrong?

1 Answer 1

1

Have the spy return a promise.

With ES2015:

spyOn(storesServiceMock, 'getStores').and.returnValue(Promise.resolve({name : 'TestName', country : 'TestCountry'}));

With $q:

spyOn(storesServiceMock, 'getStores').and.callFake(function() {
    var deferred = $q.defer();
    deferred.resolve({name : 'TestName', country : 'TestCountry'}));
    return deferred.promise;
});
Sign up to request clarification or add additional context in comments.

4 Comments

it works on chrome and firefox but throws and error on ie, ReferenceError: 'Promise' is not defined at Anonymous function
Sorry, you'll need a newer browser or use something like Babel to transpile (or create a promise using angulars $q library).
well, something is still going wrong with my test. It passes with expect(scope.stores).toBeDefined(); and expect(scope.stores).toBeUnDefined(); ,that shouldn't happen and still not working expect(scope.stores.lenth).toBeLessThan(2), got can not get the 'length' property of null or undefined
You have to call $scope.$digest() before asserting your store is populated, promises are asynchronous.

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.