使用 Rspec 存根 File.open

2024-01-21

我正在尝试存根 File.open 以测试读取 CSV 文件的方法。

这是模型:

class BatchTask
  def import(filename)
    CSV.read(filename, :row_sep => "\r", :col_sep => ",")
  end
end

这是规范代码:

let(:data) { "title\tsurname\tfirstname\rtitle2\tsurname2\tfirstname2\r"}
let(:result) {[["title","surname","firstname"],["title2","surname2","firstname2"]] }

it "should parse file contents and return a result" do
  File.stub(:open).with("file_name","rb") { StringIO.new(data) }
  person.import("file_name").should == result
end

然而,当我尝试这样做时,我得到(堆栈跟踪):

Errno::ENOENT in 'BatchTask should parse file contents and return a result'
No such file or directory - file_name
/Users/me/app/models/batch_task.rb:4:in `import'
./spec/models/batch_task_spec.rb:10:

Finished in 0.006032 seconds

我一直在用我的头撞这个,不明白我做错了什么。任何帮助将不胜感激!


提供堆栈跟踪会很有帮助,尽管我会猜测为什么会发生这种情况。另外,我相信你在这里的方法不好,我将详细说明我认为你应该如何测试。

简单来说,我认为CSV.read不使用File.open。它可以使用Kernel#open或在 Ruby 中打开文件的各种其他方式。你不应该存根File.open无论如何,在这样的测试中。

有一本很棒的书叫以测试为指导不断发展面向对象的软件 http://www.growing-object-oriented-software.com/有一个需求规则:

您控制的类/接口上仅存根方法

原因很简单。当您进行测试双打(存根)时,主要原因是接口发现 - 您想要弄清楚类的接口应该是什么样子,而双打为您提供了简洁的反馈。还有一个次要原因 - 在某些情况下(当库不是非常可存根时),存根外部库往往非常棘手。因此,您可以在这里采取几种不同的方法,我将列举:

  1. 您可以在集成中进行测试。您可以在每个测试中创建文件并传递路径名(这很好)。
  2. 您可以分解您的解析方式。而不是将文件名传递给CSV.read,当你经过空地时找到一条路File然后将其存入测试中。即,让您的代码打开文件而不是CSV。这样你就可以轻松地存根它
  3. Stub CSV.read反而。这可能有点戏剧性,但本质上,您不是在测试您的代码,而是在测试CSV图书馆。它应该已经有自己的测试,无论如何你都不需要测试它。相反,您可以依赖它的工作原理并存根对其的调用。

其中,我可能会选择第三个。我不喜欢在单元测试中测试依赖关系。但是如果您希望测试调用该代码,我建议找到一种方法来执行第二个选项(CSV.new(file)应该可以解决问题,但我没有时间调查),如果没有其他办法,最后回到#1。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Rspec 存根 File.open 的相关文章

随机推荐