ぼろぼろ平原

困った

RSpecで「while line = gets」をテストする方法

RSpecwhile line = getsのような標準入力のループをテストしたいことがある。

Kernel.#getsARGFをレシーバとしたメソッドの省略形なので、Rspecのモック機能でARGF.getsを書き換えれば良い。

テストしたいコード:

def foo
  ary = []
  while line = gets
    ary << line.chomp
  end
  ary
end

テストコード:

require "rspec"
require "stringio"
require_relative "foo"

describe "foo" do
  it "標準入力を行ごとに配列にして返す" do
    inputs = StringIO.new("line1\nline2\n")
    allow(ARGF).to receive(:gets) { inputs.gets }
    expect(foo).to contain_exactly("line1", "line2")
  end
end

同様に、while line = Readline.readlineなどの場合にもこの方法は使える。

テストしたいコード:

require "readline"

def bar
  ary = []
  while line = Readline.readline
    ary << line.chomp
  end
  ary
end

テストコード:

require "rspec"
require "stringio"
require_relative "bar"

describe "bar" do
  it "標準入力を行ごとに配列にして返す" do
    inputs = StringIO.new("line1\nline2\n")
    allow(Readline).to receive(:readline) { inputs.gets }
    expect(bar).to contain_exactly("line1", "line2")
  end
end