Reputation: 125
I'm trying to setup some Unit Tests for my AngularJS app but I'm running into a problem where the Tests don't seem to run a function properly.
I have a function that reads a json file through a $http.get request and populates an array, but when I set up in my unit test to expect the length of the array expect(array.length).toBe(10)
, it always fails, yet that is the length of the array when I run the App normally. Actually if I print the length in the console.log
on the unit test it seems to always be stuck at 1.
But for example if I check some of the variables I declare manually then the expect function works properly.
Can anyone tell me what exactly am I missing here? It's seems i'm missing some of the fundamentals on how unit testing with Karma/Jasmine works.
Any help would be greatly appreciated. Thanks!
Upvotes: 0
Views: 425
Reputation: 48948
ERRONEOUS
$scope.getAllApps = function(){ $scope.isLoading = true; $http.get('../json/apps.json').then(function (data){ // ... }); $scope.isLoading = false; };
BETTER
$scope.getAllApps = function(){
$scope.isLoading = true;
$http.get('../json/apps.json').then(function (data){
// ...
}).finally(function() {
$scope.isLoading = false;
});
};
Because the $http
service in non-blocking and asynchronous, it immediately returns a promise. It does not wait for data to return from the server. The isLoading
flag needs to wait for the promise to resolve before setting the flag false
.
Upvotes: 1
Reputation: 843
Your problem is that $http.get is an asynchronous method. Unless you sepcifically tell angularjs that it needs to flush that response, it will not. The method will exit and the callback of $http.get will not happen in time for your it method to utilize its $scope transformations.
You can achieve this by expecting the call to happen with the $httpBackend API https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend
You can then do
$httpBackend.expectGET('../json/apps.json').respond(200, {mock: 'api response');
$scope.getAllApps();
$httpBackend.flush();
expect(scope.allApps.length).toBe(10);
In your unit tests you should never rely on the actual response of http calls. To ensure you are testing only the method you should always mock the response of what your API is supposed to return.
Upvotes: 1