Unit testing the AngularJS $window service

匿名 (未验证) 提交于 2019-12-03 08:35:02

问题:

I would like to unit test the following AngularJs service:

.factory('httpResponseInterceptor', ['$q', '$location', '$window', 'CONTEXT_PATH', function($q, $location, $window, contextPath){      return {          response : function (response) {              //Will only be called for HTTP up to 300              return response;          },          responseError: function (rejection) {              if(rejection.status === 405 || rejection.status === 401) {                  $window.location.href = contextPath + '/signin';              }              return $q.reject(rejection);          }      }; }]);

I have tried with the following suite:

However, it fails with the following error message:

PhantomJS 1.9.2 (Linux) Controllers CreateCurriculumCtrl should redirect to /signin if 401 or 405 FAILED     Expected 'http://localhost:9876/context.html' to equal '/bignibou/signin'. PhantomJS 1.9.2 (Linux) ERROR     Some of your tests did a full page reload!

I am not sure what is going wrong and why. Can anyone please help?

I just want to ensure the $window.location.href is equal to '/bignibou/signin'.

edit 1:

I managed to get it to work as follows (thanks to "dskh"):

 beforeEach(module('config', function($provide){       $provide.value('$window', {location:{href:'dummy'}});  }));

回答1:

You can inject stub dependencies when you load in your module:

angular.mock.module('curriculumModule', function($provide){             $provide.value('$window', {location:{href:'dummy'}});         });


回答2:

To get this to work for me I had to make a minor adjustment. It would error out and say:

TypeError: 'undefined' is not an object (evaluating '$window.navigator.userAgent')

So I added the navigator.userAgent object to get it to work for me.

$provide.value('$window', {   location:{     href:'dummy'   },   navigator:{     userAgent:{}   } });


回答3:

I faced the same problem, and went a step further in my solution. I didn't just want a mock, I wanted to replace $window.location.href with a Jasmine spy for the better ability to track changes made to it. So, I learned from apsiller's example for spying on getters/setters and after creating my mock, I was able to spy on the property I wanted.

First, here's a suite that shows how I mocked $window, with a test to demonstrate that the spy works as expected:

describe("The Thing", function() {     var $window;      beforeEach(function() {         module("app", function ($provide) {             $provide.value("$window", {                 //this creates a copy that we can edit later                 location: angular.extend({}, window.location)             });         });          inject(function (_$window_) {             $window = _$window_;         });     });      it("should track calls to $window.location.href", function() {         var hrefSpy = spyOnProperty($window.location, 'href', 'set');          console.log($window.location.href);         $window.location.href = "https://www.google.com/";         console.log($window.location.href);          expect(hrefSpy).toHaveBeenCalled();         expect(hrefSpy).toHaveBeenCalledWith("https://www.google.com/");     }); });

As you can see above, the spy is generated by calling the below function: (it works for both get and set)

function spyOnProperty(obj, propertyName, accessType) {     var desc = Object.getOwnPropertyDescriptor(obj, propertyName);      if (desc.hasOwnProperty("value")) {         //property is a value, not a getter/setter - convert it         var value = desc.value;          desc = {             get: function() { return value; },             set: function(input) { value = input; }         }     }      var spy = jasmine.createSpy(propertyName, desc[accessType]).and.callThrough();      desc[accessType] = spy;     Object.defineProperty(obj, propertyName, desc);      return spy; }

Lastly, here's a fiddle demonstrating this in action. I've tested this against Angular 1.4, and Jasmine 2.3 and 2.4.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!