【问题标题】:Stubbing File.open with Rspec使用 Rspec 存根 File.open
【发布时间】:2012-07-28 02:39:16
【问题描述】:

我正在尝试存根 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

我一直在用头撞这个,无法弄清楚我做错了什么。任何帮助将不胜感激!

【问题讨论】:

  • 添加了确切错误的堆栈跟踪

标签: ruby-on-rails rspec stubbing


【解决方案1】:

提供堆栈跟踪会很有帮助,尽管我会猜测它发生的原因。另外,我认为您在这里的方法不好,我将详细说明我认为您应该如何测试。

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

有一本很棒的书叫Growing Object-Oriented Software Guided by Tests,里面有一个需求规则:

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

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

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

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

【讨论】:

  • 感谢您的周到回答!这绝对给了我一个很好的视角来思考如何前进。存根 CSV.read 方法似乎是最好的方法。再次感谢!
猜你喜欢
  • 2013-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多