好的,因此根据您想要观察到的最新评论,您正在记录一些输出。这是一个示例,您通过将 STDOUT 替换为 StringIO 实例来观察此行为:
# foo.rb
require 'rubygems'
require 'rspec'
require 'rspec/autorun'
require 'stringio'
class Foo
def something
puts 1
puts 'a'
puts 'bar' if true # some complex logic
puts :x
end
end
describe Foo do
describe '#something' do
context "and something complex happens" do
let(:io){ StringIO.new }
it "logs to STDOUT" do
$stdout = io
Foo.new.something
expect(io.tap(&:rewind).read).to include("bar\n")
end
end
end
end
这会起作用,但是这样做的副作用远远超出您的具体示例,因为我们正在更改全局$stdout
. 这可以通过使用带有构造函数默认值的穷人依赖注入来改进:
class Foo
def initialize(io=STDOUT)
@io = io
end
def something
puts 1
puts 'a'
puts 'bar' if true # some complex logic
puts :x
end
protected
def puts(*args)
@io.puts *args
end
end
describe Foo do
describe '#something' do
context "and something complex happens" do
let(:io){ StringIO.new }
it "logs to STDOUT" do
Foo.new(io).something
expect(io.tap(&:rewind).read).to include("bar\n")
end
end
end
end
在上面的例子中,我们让自己能够传入我们将要放入的 IO 对象。这让我们可以观察行为而不会产生超出测试范围的副作用,并且以一种让我们正在测试的对象保持真实的方式(即:我们没有像以前那样修改对象本身,而是现在已删除有关使用as_null_object
建议的评论)。
您还可以在构造函数上使用选项哈希并将惰性分配推入initialize
自身:
def initialize(arg1, arg2, options={})
@io = options[:io] || STDOUT
end
您还可以升级您的简单puts
以使用实际的 Logger 对象。然后,您可以在一个地方测试您的记录器与 STDOUT、STDERR 或其他任何地方一起使用,并且您可以在您关心记录的所有对象中测试它正在适当地记录到info
、debug
等。
您也可以从其他几个方向着手,但如果不了解您在做什么,这个潜在的答案可能已经足够长了。
希望这可以让您了解如何通过观察行为而不是依赖内部实现细节来解决此问题(例如,您使用的是puts
自身而不是print "bar\n"
另一种将文本输出到 IO 对象的方法。