用 Sinon 存根 window.location.href

Stubbing window.location.href with Sinon

我正在尝试测试一些客户端代码,为此我需要使用 Mocha/Sinon.

存根 window.location.href 属性 的值

到目前为止我已经尝试过的(using this example):

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

运行程序显示以下错误:

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

将测试代码更改为:

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

产生此错误:

TypeError: Attempted to wrap string property href as function

将函数作为第三个参数传递给 sinon.stub 也不起作用。

有没有办法提供伪造的 window.location.href 字符串,同时避免重定向(因为我在浏览器中进行测试)?

存根不能替换属性,只能替换函数。

抛出的错误强化了这一点:

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

来自文档:

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/releases/v2.0.0/stubs/


可能的解决方案

虽然许多内置对象可以被替换(用于测试),但有些不能。对于这些属性,您可以创建外观对象,然后您必须在代码中使用这些对象并能够在测试中替换它们。

例如:

var loc = {

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

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

};

用法:

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

然后你可以在你的测试中写

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

注意链式 returns() 调用。您的代码中还有另一个错误:第三个参数必须是一个函数,而不是另一种类型的值。是回调,不是属性应该是什么return.

See the source code of stub()

使用 window.location.assign(url) 而不是覆盖 window.location 的值。然后你可以在 window.location 对象上存根 assign 方法。

http://www.w3schools.com/jsref/met_loc_assign.asp


更新:我在无头浏览器中对此进行了测试,但如果您 运行 在 Chrome 中进行测试,它可能无法正常工作。参见

您需要使用 global 模拟 window 对象,以便在 beforeEachit

中进行测试

例如

it('should compose a Log', () => {
   global.window = {
       location: {
           href: {
               value: 'foo'
           }
       }
   }
  //.... call the funciton 
});