AngularJS - Loading module files

As you know, the built-in function of corner functions is tested inside the module for mocking XHR requests using $ httpBackend - this is nice and useful when writing unit tests.

I recently met a need for a mocking XHR in case of a file upload and found some problems.

Consider the following code:

var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", uploadProgress(event), false); xhr.addEventListener("load", uploadComplete(event), false); xhr.addEventListener("error", uploadError(event), false); xhr.addEventListener("abort", uploadAbort(event), false); xhr.open("POST", 'some url'); xhr.send(someData); 

What I want to do is to do unit testing of such code with bullying on XHR requests, but this cannot be done because the $ http service is not used here.

I tried this (and it worked, and it was possible to mock $ httpBackend):

 $http({ method: 'POST', url: 'some url', data: someData, headers: {'Content-Type': undefined}, transformRequest: angular.identity}) .then(successCallback, errorCallback); 

But in this case, I do not know how to implement the callback "progress" and "abort" callback (they are necessary and necessary if I am working now).

I saw information that the latest Angular supports a progress callback for promises (not sure though it is integrated with the $ http service), but what about canceling the callback?

Any ideas, or maybe you've met something similar before?

+6
source share
2 answers

If the $http service does not provide you with everything you need, you can unit test create the first block of code. First of all, change your code to use the Angular $window . This is just a service wrapper, but it allows you to mock an object in your tests. So you want to do this:

 var xhr = new $window.XMLHttpRequest(); 

Then in your tests just mock him and use spies.

 $window.XMLHttpRequest= angular.noop; addEventListenerSpy = jasmine.createSpy("addEventListener"); openSpy = jasmine.createSpy("open"); sendSpy = jasmine.createSpy("send"); xhrObj = { upload: { addEventListener: addEventListenerSpy }, addEventListener: addEventListenerSpy, open: openSpy, send: sendSpy }; spyOn($window, "XMLHttpRequest").andReturn(xhrObj); 

From there, you can force different spies to return whatever you want for different tests.

+11
source

You have to make fun of $http and control any pending ones since you want more control over your test. Basically, mock $http provider and maintain a custom implementation that puts it off, and then play with it.

You do not have to worry about whether $http working correctly or not, because it has to be and has already been tested. Therefore, you should scoff at it and only worry while checking your piece of code.

You should go something like this:

 describe('Testing a Hello World controller', function() { beforeEach(module(function($provide) { $provide.provider('$http', function() { this.$get = function($q) { return function() { var deferred = $q.defer(), promise = deferred.promise; promise.$$deferred = deferred; return promise; } }; }); })); it('should answer to fail callback', inject(function(yourService, $rootScope) { var spyOk = jasmine.createSpy('okListener'), spyAbort = jasmine.createSpy('abortListener'), spyProgress = jasmine.createSpy('progressListener'); var promise = yourService.upload('a-file'); promise.then(spyOk, spyAbort, spyProgress); promise.$$deferred.reject('something went wrong'); $rootScope.$apply(); expect(spyAbort).toHaveBeenCalledWith('something went wrong'); })); }); 

And your service is simple:

 app.service('yourService', function($http) { return { upload: function(file) { // do something and return $http({...}); } }; }); 

Just note that promises notification is only available in the latest RC version. So, if you can't use it, just come up with an example and mock XHR events, etc.

Also note that you must have one test case for each of the callbacks (failure, success and progress) in order to follow the KISS principle.

+2
source

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


All Articles