Mocking $window when testing services

7,080 views
Skip to first unread message

ronen...@gmail.com

unread,
Feb 16, 2013, 12:34:01 PM2/16/13
to ang...@googlegroups.com
Hi,

I'm writing some unit tests for my services and I need to mock the $window service. When I try to mock it and run the tests (using Testacular) I'm getting this error:

TypeError: Cannot read property 'userAgent' of undefined
    at $SnifferProvider.$get (C:/server/www/base/app/lib/angular/angular.js:8221:72)
 
This happens at what seems to be a private service. If I add a "navigator" property to my mocked $window I won't be getting that error the the rest of my tests would go smoothly. Here's how I mock the $window service:

describe('Module', function () {
    var mock = {};

    beforeEach(function() {
        module('Module');

        module(function($provide) {
            $provide.value('$window', mock);
        });
    });

    describe('Service', function () {
        // ...
    });
});

Am I doing something wrong or is this a bug?

Thanks!

Peter Bacon Darwin

unread,
Feb 16, 2013, 12:39:54 PM2/16/13
to ang...@googlegroups.com
Alternatively you could get hold of the $window service and "spy" on its methods:

describe('Module', function () {
    var $window;

    beforeEach(inject(function(_$window_) {
        $window = _$window_;
        spyOn($window, 'whateverFn');

        module('Module');
    });

    describe('Service', function () {
        // ...
        expect($window.whateverFn).toHaveBeenCalled();
    });
});


--
You received this message because you are subscribed to the Google Groups "AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to angular+u...@googlegroups.com.
To post to this group, send email to ang...@googlegroups.com.
Visit this group at http://groups.google.com/group/angular?hl=en-US.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

ronen...@gmail.com

unread,
Feb 17, 2013, 2:16:56 AM2/17/13
to ang...@googlegroups.com
That would work but I still want to mock the $window service with a fake one.

Does anyone have an idea on how to solve it?

Thanks!

Peter Bacon Darwin

unread,
Feb 17, 2013, 2:22:54 AM2/17/13
to ang...@googlegroups.com

Create a module that defines the $window service and load this before you app module

Pete
...from my mobile.

--

Marcin Wosinek

unread,
Feb 17, 2013, 6:59:49 AM2/17/13
to ang...@googlegroups.com
As I understood Peter Bacon Darwin's solution, here is a way to achieve it:

beforeEach(function () {
module(function($provide) {
$provide.value('$resource', function (argUrl) {
url = argUrl;
return {
save: function (argObject) {
object = argObject;
}
}
});
});
});

I'm creating therefore my own object, and setting it in $provieder to
be used instead of original ones.

2013/2/17 Peter Bacon Darwin <pe...@bacondarwin.com>:

Neil Manuell

unread,
Jul 4, 2013, 6:25:21 AM7/4/13
to ang...@googlegroups.com
@ronen

I know this is possibly too late for you, but it may help future searchers:

all you have to do is to create some properties on your mock object

 var mock = 
{
  navigator: {
                  userAgent:{}
                 }
};

Calinoiu Alexandru

unread,
Jul 22, 2013, 11:53:08 AM7/22/13
to ang...@googlegroups.com
Hi,

I've tried this mock but for some reason the test will fail with

TypeError: $document[0] is undefined in /home/calin/Projects/MetricAlertsWeb/vendor/assets/javascripts/angular.js (line 3876)

My code is trying to test a directive, here is my beforeEach:

  beforeEach(function () {
    module('helperModule');

    var mock =
    {
      navigator: {
        userAgent:{}
      }
    };

    module(function ($provide) {
      $provide.value('$window', mock);
    });

    inject(function (_$compile_, _$rootScope_) {
      $compile = _$compile_;
      $rootScope = _$rootScope_;
    });
  })

duckmole

unread,
Aug 2, 2013, 9:18:45 AM8/2/13
to ang...@googlegroups.com
Hi, 

Maybe you're already find a solution.
In my test I've had that kind of error. I added a document key in the mock and it solved the error

your new mock will be thing like :
var mock;
            mock = {
              location: 'val',
              document: [
                {
                  createElement: function() {
                    return null;
                  }
                }
              ]
            };
Reply all
Reply to author
Forward
0 new messages