一般的方法是使此类对象可交换。
在您的情况下,gets 在$stdin 上被隐式调用。所以你可以做一个可选的
名为“输入”的参数默认为$stdin 并调用它。
这是一个简单的计算器示例,它接受一些输入并返回结果。
class Calculator
def initialize input = $stdin
@input = input
end
def process
eval @input.gets
end
end
现在您可以运行puts Calculator.new.process,输入1 + 2,您将看到3。
您不需要任何特殊工具来测试它,因为您可以轻松地传递一个 IO 对象
并在您的测试中直接写入它。 IO.pipe 是一个不错的选择:
describe "Calculator" do
before do
reader, @writer = IO.pipe
@calc = Calculator.new(reader)
end
it "can sum up two numbers" do
@writer.puts "1 + 2"
result = @calc.process
result.should eq(3)
end
end
您也可以使用 StringIO 代替,它不是真正的 IO,并且不需要类似 UNIX 的环境。
虽然每次写入时都需要倒带。
require "stringio"
describe "Calculator" do
before do
@input = StringIO.new
@calc = Calculator.new(@input)
end
it "can sum up two numbers" do
@input.puts "1 + 2"
@input.rewind
result = @calc.process
result.should eq(3)
end
end
与存根方法相比,这种方法的优势在于测试不那么脆弱,设计也更好。
测试不那么脆弱,因为如果您决定更改实现并使用 getc
例如,您不需要更改测试,而不是获取(一个接一个地读取字符)。
而且设计更好,因为现在您可以轻松地从不同来源发出命令
例如文件Calculator.new(File.open("calculated_list.txt"))。或者你的假 IO
可以在你的测试中使用!