使用 Rspec 存根 File.open [英] Stubbing File.open with Rspec

查看:57
本文介绍了使用 Rspec 存根 File.open的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm attempting to stub File.open in order to test a method I have that reads a CSV file.

这是模型:

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

但是,当我尝试这样做时,我得到了(堆栈跟踪):

However, when I attempt to do this I get (stacktrace):

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

我一直在用头撞这个,但不知道我做错了什么.任何帮助将不胜感激!

I've been banging my head against this one and can't figure out what I'm doing wrong. Any help would be greatly appreciated!

推荐答案

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

It would be helpful to provide a stacktrace, although I will make a guess why it happens. Also, I believe you're approach in here is not good and I will elaborate on how I believe you should test.

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

Simply, I think that CSV.read does not use File.open. It can use Kernel#open or various other ways a file can be opened in Ruby. You should not stub File.open in a test as this anyway.

有一本书叫做Growing Object-Oriented Software Guided by Tests 有一个需求规则:

There is a great book called Growing Object-Oriented Software Guided by Tests that has a need rule:

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

Stub only methods on classes/interfaces you control

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

There is a very simple reason for that. When you're doing test doubles (stub), the primary reason is interface discovery - you want to figure out how the interface of your class should look like and doubles provide you with neat feedback. There is also a secondary reason - stubbing external libraries tends to be quite tricky in some cases (when the library is not extremely stubbable). Thus, you can take a few different approaches here, that I will enumerate:

  1. 您可以在集成中进行测试.您可以在每个测试中创建文件并传递路径名(这很好).
  2. 您可以分解解析方式.与其将文件名传递给 CSV.read,不如在传递打开的 File 时找到方法 然后在测试中存根.即,让您的代码打开文件而不是 CSV.这样你就可以轻松地存根
  3. 存根 CSV.read. 这可能有点戏剧化,但本质上,您不是在测试代码,而是在测试 CSV 库.它应该已经有了自己的测试,无论如何你都不需要测试它.相反,您可以依赖它的工作原理,并存根对它的调用.
  1. You can test in integration. You can either create the file in each test and pass the pathname (which is fine).
  2. You can break down the way you're parsing. Instead of passing a filename to CSV.read, find a way when you pass an open File and then stub that in the test. i.e., have your code open the file instead of CSV. That way you can stub it easily
  3. Stub CSV.read instead. That might be a bit dramatic, but in essence, you're not testing your code, you're testing the CSV library. It should already have its own tests and you don't need to test it anyway. Instead, you can rely on the fact that it works and just stub the call to it.

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

Out of those, I would probably go with the third one. I don't like testing dependencies in my unit tests. But if you want your test to call that code, I suggest finding a way to do the second option (CSV.new(file) should do the trick, but I don't have time to investigate) and finally fall back to #1 if nothing else works.

这篇关于使用 Rspec 存根 File.open的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆