Sinon.JS用于window.location.search的存根

5
我正在尝试测试一个简单的函数,该函数调用window.location.search。我试图理解如何存根此调用,以便我可以返回我选择的URL。
函数:
getParameterByName: (name) =>    
  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]")
  regexS = "[\\?&]" + name + "=([^&#]*)"
  regex = new RegExp(regexS)    
  results = regex.exec(window.location.search) //Stub call to window.location.search
  if(results == null)
    return ""
  else
    return decodeURIComponent(results[1].replace(/\+/g, " "))

测试案例:
describe "Data tests", () ->
  it "Should parse parameter from url", () ->        
    data = new Data()

    console.log("search string: " + window.location.search) //prints "search string:"
    window.location.search = "myUrl"
    console.log("search string: " + window.location.search) //prints "search string:"
    console.log(data.getParameterByName('varName'))

    expect(true).toBe(true)

我的最初尝试是直接返回一个值,如下所示:
sinon.stub(window.location.search).returns("myUrl")

当然,这样做是行不通的。我认为我没有正确指定存根,但这表明了我的意图。
如果您有解决此问题的任何想法,将不胜感激。
2个回答

6

如前所述,您无法直接模拟window.location。我的情况也不能使用mylib.search包装器的方法。因此,我将对window.location.search的调用分解成自己的函数。我的新类如下:

getParameterByName: (name) =>
  console.log("name: #{name}")
  name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]")
  regexS = "[\\?&]" + name + "=([^&#]*)"
  regex = new RegExp(regexS)
  results = regex.exec(@getWindowLocationSearch())
  if(results == null)
    return ""
  else
    return decodeURIComponent(results[1].replace(/\+/g, " "))

getWindowLocationSearch:() =>
  window.location.search

接着,在我的测试用例中,我将该函数替换为我的测试代码,如下所示:

describe "Data tests", () ->
  it "Should parse parameter from localhost url", () ->
    goodUrl = "http://localhost:3333/?token=val1"

    Data::getWindowLocationSearch = () -> return goodUrl
    unit = new Data()
    result = unit.getParameterByName("token")

    expect(result).toBe("val1")

如果您不会阅读Coffeescript,下面列出了相应的JavaScript代码:

it("Should parse parameter from localhost url", function() {
  var goodUrl, result, unit;
  goodUrl = "http://localhost:3333/?token=val1";
  Data.prototype.getWindowLocationSearch = function() {
    return goodUrl;
  };
  unit = new Data();
  result = unit.getParameterByName("token");
  expect(result).toBe("val1");
  return expect(true).toBe(true);
});

作为我的惯常经历,JavaScript 的工作解决方案并非到达那里的旅程那样痛苦。非常感谢您的评论和贡献。

2

更新: 看起来window.location是一个特殊的情况,参见这个讨论:https://groups.google.com/forum/?fromgroups#!topic/sinonjs/MMYrwKIZNUU%5B1-25%5D

解决这个问题最简单的方法是编写一个包装函数来包装window.location,然后进行存根操作:

mylib.search = function (url) {
  window.location.search = url;
};

在您的测试中:

sinon.stub(mylib, 'search').returns("myUrl")

尝试这个:
sinon.stub(window.location, 'search').returns("myUrl")

1
我之前尝试过那个方法,现在又尝试了一遍:TypeError: 尝试将字符串属性search包装成函数 - Michael D Johnson
抱歉,window.location.search是一个字符串而不是函数,因此您无法对其进行存根。请使用赋值语句替换存根:window.location.search = "myUrl" - Chris Salzberg
奇怪的是,在打印控制台之前和之后的结果都为空字符串,所以我不确定出了什么问题。赋值好像没有生效。我更新了我的代码以展示我的测试案例。 - Michael D Johnson
好的,我认为这实际上比我最初想象的要难。请参阅此讨论:https://groups.google.com/forum/?fromgroups#!topic/sinonjs/MMYrwKIZNUU%5B1-25%5D - Chris Salzberg
这在我的类上不起作用,因为我必须使用原型来覆盖函数。Sinon的存根在我的类中无法工作,因为存在这个问题。 - Michael D Johnson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接