如何在不显式调用Kernel的情况下模拟Kernel.open或open-uri?

时间:2012-12-04 00:17:11

标签: ruby rspec mocking tdd open-uri

如何在RSpec中模拟此调用?

require 'open-uri'
class FileFoo < ActiveRecord::Base
  def download image_url
    open("tmp/#{file}", 'wb') do |file|
      file << open(image_url).read
    end
  end
end

尝试模拟FileFoo.open,但这不起作用,因为我使用的是下载文件,而不是返回值。

将代码更改为file << Kernel.open(image_url).read,并使用以下内容:

Kernel.stub_chain(:open, :read).and_return(File.read image_fixture)

这样可以正常工作,但有没有办法模拟Kernel.open().read,而无需显式调用内核?

2 个答案:

答案 0 :(得分:2)

我经常认为在这种情况下更好的测试不是模拟特定的文件系统调用,而是使用类似fakefs的gem来存档文件系统。

我更多地谈论了一篇名为Fake It!的博客文章。

这个想法是特定文件系统调用的存根非常脆弱,但是在单元测试中写入实际文件系统也不一定是可取的。像 fakefs 这样的东西在很多时候都是一种不错的快乐媒介。

答案 1 :(得分:1)

我认为这很难,因为方法download的设计很差。它做了两件事:

  1. 通过HTTP获取文件
  2. 将其保存到磁盘
  3. 这两个 单独的函数 都应该进行测试,第一个应该被模拟。我没有看到任何理由来模拟文件系统,因为保存文件(很小)是快速且容易测试的。

    如果方法分为2种方法,那么:

    1. fetch with http会返回该文件。
    2. save file会保存它。
    3. 这种方法使得模拟和测试变得简单。