我知道Stack Overflow中涵盖了这个主题,但是他们提供的任何解决方案都不适用于我 . 2天陷入困境......开始有点绝望了 .

我原来的代码:

url = 'https://someurl/picture.jpg'
file = File.open('new_picture.jpg', 'wb') do |fo|
  fo <<  open(url).read
end

我无法弄清楚如何将此打开 . 我尝试了什么(在一百个小的替代品中,都失败了)

let(:buffer) {StringIO.new}
let(:picture) {'picture.jpg'}
let(:content) { 'this is just a content to mock up the file' }

before do
  # previous stuff..
  allow(File).to receive(:open).with(picture, 'wb').and_yield(buffer)
end

it 'downloads the image' do
  expect(File).to receive(:open).with(picture,'wb')
  call # this is the way to call the method that contains File.open
end

所有时间都收到错误:

expected: ("picture.jpg", "wb")
got: ("/var/folders/55/1mv73gd50779nsdwwh6vkp280000gn/T/open-uri20180315-23631-9dokgj", 2562, {:perm=>384})

我错过了什么?我也在块 File.open(picture) { |f| f.write(content) } 内尝试过 . 如果我不调用 call ,它会工作 . 所以我有一个绿色测试,它永远不会进入我想测试的真实方法 .

我的主要目标:从调用此调用的类中存储File.open . 然后我只是希望随时都能获得开放......只是我想要那个!

UPDATED - whole test

require 'pry'
require 'spec_helper'

describe Downloader do
  let(:call) { Downloader.call }
  let(:path) { '/Users/testUser/Downloads/picture.jpg' }

  it 'returns a path' do
    expect(call).to be_a_kind_of(String)
  end

  xcontext 'when the image exists' do
    before { allow_any_instance_of(File).to receive(:exist?).and_return(true) }

    it 'returns the correct path' do
      allow(subject).to receive(:get_existing_file).and_return(path)
      expect(call).to match(/picture/)
      expect(call).to match(/Downloads/)
      expect(call).to match(/Users/)
    end
    it 'does not modify the system' do
      expect(File).not_to receive(:open)
    end
  end
  context 'when the image does not exists' do
    let(:buffer) { StringIO.new }
    let(:picture) { 'picture.jpg' }
    let(:content) { 'this is just a content to mock up the file' }

    before do
      allow(File).to receive(:exist?).and_return(false)
      allow(File).to receive(:open).with(picture, 'wb').and_yield(buffer)
    end

    it 'downloads the image' do
      >>>> GOT STUCK HERE, just removed what I had 
      call

    end
  end
end

SOLUTION

最后,我决定使用FakeFs来模拟FileSystem . 这是我的规范,检查它是否存在文件或不存在 .

require 'fakefs/spec_helpers'
require 'spec_helper'

describe Downloader do
  include FakeFS::SpecHelpers
  let(:call) { Downloader.call }
  let(:path) { '/Users/testUser/Downloads/example_picture.jpg' }
  let(:buffer) { instance_double(File, path: 'picture.jpg') }

  before do
    config = File.expand_path('~/Downloads', __FILE__)
    FakeFS::FileSystem.clone(config)
    allow(File).to receive(:open).and_return(buffer)
  end
  it 'returns a path' do
    expect(call).to be_a_kind_of(String)
  end

  context 'when the image exists' do
    before { allow_any_instance_of(File).to receive(:exist?).and_return(true) }

    it 'returns the correct path' do
      allow(subject).to receive(:get_existing_file).and_return(path)
      expect(call).to match(/example_picture/)
      expect(call).to match(/Downloads/)
      expect(call).to match(/Users/)
    end
    it 'does not modify the system' do
      expect(File).not_to receive(:open)
    end
  end
  context 'when the image does not exists' do
    before { allow(File).to receive(:exist?).and_return(false) }
    it 'downloads the image' do
      expect(File).to receive(:open)
      call
    end
    it 'puts in the right folder' do
      expect(Dir.pwd).not_to match(/Downloads/)
      call
      expect(Dir.pwd).to match(/Downloads/)
    end
    it 'returns the path with the new image' do
      result = call
      expect(result).to match(/Downloads/)
      expect(result).to match(/picture/)
    end
  end
end