有没有打开一个 StringIO 来写这样的东西?
Is there such a thing as opening a StringIO for writing?
我正在尝试使用 RSpec 来测试写入文件的 class。但我希望测试速度更快,所以我不想使用真实文件并写入磁盘,而是想在测试中使用 StringIO 并写入内存。
以一种非常简单的方式,假设我有这个测试:
RSpec.describe Writer do
it 'replaces the contents of the file' do
file = StringIO.new('foo')
writer = described_class.new(file)
one_contact = [{ 'name' => 'name', 'address' => 'address' }]
writer.write(one_contact)
expect(file.string).to eq('[{"name":"name1","address":"address1"}]')
end
end
假设作者 class 是这样的:
require 'json'
class Writer
def initialize(file)
@file = file
end
def write(contacts)
file.truncate(0)
file.write(contacts.to_json)
file.flush
end
private
attr_reader :file
end
当我 运行 通过 Rspec 测试时,我得到错误:
Failure/Error: file.truncate(0)
IOError:
not opened for writing
如果我将 truncate
更改为其他内容,那么我会在 file
上调用 write
的行中收到此错误。
但是,如果我撬开它,它会起作用:
$ pry
[1] pry(main)> require_relative 'lib/db/writer'
=> true
[2] pry(main)> file = StringIO.new('foo')
=> #<StringIO:0x0000563c99220f70>
[3] pry(main)> writer = Writer.new(file)
=> #<Writer:0x0000563c98ff8950 @file=#<StringIO:0x0000563c99220f70>>
[4] pry(main)> one_contact = [{ 'name' => 'name', 'address' => 'address' }]
=> [{"name"=>"name", "address"=>"address"}]
[5] pry(main)> writer.write(one_contact)
=> #<StringIO:0x0000563c99220f70>
[6] pry(main)> file.string
=> "[{\"name\":\"name\",\"address\":\"address\"}]"
如果我在普通 ruby 文件中执行此操作,并且 运行 使用 ruby,例如:
require_relative 'lib/db/writer'
file = StringIO.new('foo')
writer = Writer.new(file)
one_contact = [{ 'name' => 'name1', 'address' => 'address1' }]
writer.write(one_contact)
puts file.string
同样有效。
这是一个超级简单的 Ruby 应用程序,没有依赖项或框架,这就是 Gemfile 的样子:
source 'https://rubygems.org'
ruby '2.5.1'
gem 'sqlite3'
group :test do
gem 'coveralls', require: false
gem 'pry'
gem 'rake'
gem 'rspec'
gem 'rubocop', require: false
end
实际 gem 版本:
- sqlite3 (1.3.13)
- 工作服 (0.8.22)
- 撬 (0.11.3)
- 耙子 (12.3.1)
- rspec (3.7.0)
- rubocop (0.58.1)
如何打开一个StringIO进行写入?我想在测试时继续写入内存而不是磁盘。
这是你的问题:
# frozen_string_literal: true
您的字符串 contents
已冻结,无法修改。 StringIO用上面的IOError
.
表示
我正在尝试使用 RSpec 来测试写入文件的 class。但我希望测试速度更快,所以我不想使用真实文件并写入磁盘,而是想在测试中使用 StringIO 并写入内存。
以一种非常简单的方式,假设我有这个测试:
RSpec.describe Writer do
it 'replaces the contents of the file' do
file = StringIO.new('foo')
writer = described_class.new(file)
one_contact = [{ 'name' => 'name', 'address' => 'address' }]
writer.write(one_contact)
expect(file.string).to eq('[{"name":"name1","address":"address1"}]')
end
end
假设作者 class 是这样的:
require 'json'
class Writer
def initialize(file)
@file = file
end
def write(contacts)
file.truncate(0)
file.write(contacts.to_json)
file.flush
end
private
attr_reader :file
end
当我 运行 通过 Rspec 测试时,我得到错误:
Failure/Error: file.truncate(0)
IOError:
not opened for writing
如果我将 truncate
更改为其他内容,那么我会在 file
上调用 write
的行中收到此错误。
但是,如果我撬开它,它会起作用:
$ pry
[1] pry(main)> require_relative 'lib/db/writer'
=> true
[2] pry(main)> file = StringIO.new('foo')
=> #<StringIO:0x0000563c99220f70>
[3] pry(main)> writer = Writer.new(file)
=> #<Writer:0x0000563c98ff8950 @file=#<StringIO:0x0000563c99220f70>>
[4] pry(main)> one_contact = [{ 'name' => 'name', 'address' => 'address' }]
=> [{"name"=>"name", "address"=>"address"}]
[5] pry(main)> writer.write(one_contact)
=> #<StringIO:0x0000563c99220f70>
[6] pry(main)> file.string
=> "[{\"name\":\"name\",\"address\":\"address\"}]"
如果我在普通 ruby 文件中执行此操作,并且 运行 使用 ruby,例如:
require_relative 'lib/db/writer'
file = StringIO.new('foo')
writer = Writer.new(file)
one_contact = [{ 'name' => 'name1', 'address' => 'address1' }]
writer.write(one_contact)
puts file.string
同样有效。
这是一个超级简单的 Ruby 应用程序,没有依赖项或框架,这就是 Gemfile 的样子:
source 'https://rubygems.org'
ruby '2.5.1'
gem 'sqlite3'
group :test do
gem 'coveralls', require: false
gem 'pry'
gem 'rake'
gem 'rspec'
gem 'rubocop', require: false
end
实际 gem 版本:
- sqlite3 (1.3.13)
- 工作服 (0.8.22)
- 撬 (0.11.3)
- 耙子 (12.3.1)
- rspec (3.7.0)
- rubocop (0.58.1)
如何打开一个StringIO进行写入?我想在测试时继续写入内存而不是磁盘。
这是你的问题:
# frozen_string_literal: true
您的字符串 contents
已冻结,无法修改。 StringIO用上面的IOError
.