Francesco Pezzella Francesco Pezzella - 26 days ago 29
Javascript Question

Stubbing window.location.href with Sinon

I am trying to test some client-side code and for that I need to stub the value of

window.location.href
property using Mocha/Sinon.

What I have tried so far (using this example):

describe('Logger', () => {
it('should compose a Log', () => {
var stub = sinon.stub(window.location, 'href', 'http://www.foo.com');
});
});


The runner displays the following error:


TypeError: Custom stub should be a function or a property descriptor


Changing the test code to:

describe('Logger', () => {
it('should compose a Log', () => {
var stub = sinon.stub(window.location, 'href', {
value: 'foo'
});
});
});


Which yields this error:


TypeError: Attempted to wrap string property href as function


Passing a function as third argument to
sinon.stub
doesn't work either.

Is there a way to provide a fake
window.location.href
string, also avoiding redirection (since I'm testing in the browser)?

Answer

Stubs cannot replace attributes, only functions.

The error thrown reinforces this:

TypeError: Custom stub should be a function or a property descriptor

From the documentation:

When to use stubs?

Use a stub when you want to:

  1. Control a method’s behavior from a test to force the code down a specific path. Examples include forcing a method to throw an error in order to test error handling.

  2. When you want to prevent a specific method from being called directly (possibly because it triggers undesired behavior, such as a XMLHttpRequest or similar).

http://sinonjs.org/docs/#stubs


Possible solution

While many builtin objects can be replaced (for testing) some can't. For those attributes you could create facade objects which you then have to use in your code and being able to replace them in tests.

For example:

var loc = {

    setLocationHref: function(newHref) {
        window.location.href = newHref;
    },

    getLocationHref: function() {
        return window.location.href;
    }

};

Usage:

loc.setLocationHref('http://acme.com');

You can then in your test write

var stub = sinon.stub(loc, 'setLocationHref').returns('http://www.foo.com');

Note the chained returns() call. There was another error in your code: the third argument has to be a function, not value on another type. It's a callback, not what the attribute should return.

See the source code of stub()

Comments