使用Sinon对window.location.href进行存根

Fra*_*lla 24 javascript mocha.js stubbing sinon

我正在尝试测试一些客户端代码,为此我需要window.location.href使用Mocha/Sinon 来存储属性的值.

到目前为止我尝试过的(使用此示例):

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

运行器显示以下错误:

TypeError:自定义存根应该是函数或属性描述符

将测试代码更改为:

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

这产生了这个错误:

TypeError:尝试将字符串属性href包装为函数

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

有没有办法提供假window.location.href字符串,也避免重定向(因为我在浏览器中测试)?

Kha*_*edP 18

您需要使用global嘲笑的window对象为您的测试中beforeEachit

例如

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

  • 如果我错了,请纠正我,但是覆盖全局对象会直接检查其余的测试文件吗?这意味着它将被任何其他测试用例覆盖.可能不是一个问题,而是一个FYI. (7认同)
  • 我不确定这对你们有什么作用,因为出现错误提示无法分配给只读属性。 (5认同)
  • @perry 为了在测试开始时解决这个问题,我保存了全局对象 `const originalWindow = global.window`,然后在测试结束时我将它恢复为 `global.window = originalWindow`。 (2认同)

Dan*_*ews 13

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

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


更新:我在无头浏览器中对此进行了测试,但如果您在Chrome中运行测试,它可能无效.请参阅@ try-catch-finally的响应.

  • 这个答案是对的.你不能重新分配(stub)`location.assign`,至少在Chrome中是一个`window.location.assign = function(){console.log("meh"); }`没有效果.当调用`location.assign()时,我得到`未捕获的TypeError:无法在'Location'上执行'assign':需要1个参数,但只有0表示.(这表示本机方法抱怨缺少的参数). (3认同)

try*_*lly 10

存根不能替换属性,只能替换功能.

抛出的错误强化了这个:

TypeError:自定义存根应该是函数或属性描述符

从文档:

什么时候使用存根?

如果您想要使用存根:

  1. 从测试控制方法的行为以强制代码沿特定路径下移.示例包括强制方法抛出错误以测试错误处理.

  2. 当您想要阻止直接调用特定方法时(可能是因为它触发了不需要的行为,例如XMLHttpRequest或类似行为).

http://sinonjs.org/releases/v2.0.0/stubs/


可能解决方案

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

例如:

var loc = {

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

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

};
Run Code Online (Sandbox Code Playgroud)

用法:

loc.setLocationHref('http://acme.com');
Run Code Online (Sandbox Code Playgroud)

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

var stub = sinon.stub(loc, 'setLocationHref').returns('http://www.foo.com');
Run Code Online (Sandbox Code Playgroud)

请注意链接的returns()电话.您的代码中还有另一个错误:第三个参数必须是函数,而不是另一个类型的值.这是一个回调,而不是该属性应返回的内容.

查看源代码 stub()