简体   繁体   中英

Rspec - Stubbing gets.chomp out of the constructor

I'm writing a Mastermind game in Ruby and in the constructor of the class 'Game' I want to use gets.chomp to ask the user for its name. Pretty easy, but where I run into trouble is when testing this class in RSpec, but I can't seem to properly stub out 'gets' and 'puts', because they are in the constructor not a regular method.

class Game
  def initialize
    puts "Please enter your name:"
    @player = Player.new(gets.chomp)
  end
end

describe Game do
  Game.stub(:gets).and_return("Create Code AI")
  Game.stub(:puts)
  subject(:game) { Game.new }

  describe "#new" do
    its("player.name") { eql("Create Code AI") }
  end
end

class Player
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

I've also tried putting the stubs into 'before' and 'let' blocks amongst other things, but nothing seems to work. Any help is appreciated!

I have a method which captures stdin and stdout to help with the testing in cases like these:

require 'stringio'

module Kernel
  def capture_stdout(console_input = '')
    $stdin = StringIO.new(console_input)
    out = StringIO.new
    $stdout = out
    yield
    return out.string.strip
  ensure
    $stdout = STDOUT
    $stdin = STDIN
  end
end

Now, let's assume I want to test a method that interacts with stdin/stdout:

def greet
  name = gets
  puts "Welcome, #{name}!"
end

I would write the following test:

require 'rspec/autorun'

RSpec.describe '#say_name' do
  it 'prints name correctly' do
    input = 'Joe'
    result = capture_stdout(input) do
      greet
    end

    expect(result).to eql 'Welcome, Joe!'
  end
end

I presented the example above to illustrate how to test both console input and output.

In your case, the test could look like this:

describe Game do
  subject(:game) do
    capture_stdout('Create Code AI') { return Game.new }
  end

  describe "#new" do
    its("player.name") { eql("Create Code AI") }
  end
end

Note: In order for this to work, #player should be an accessible member of Game . So, you may want to add this to your Game class:

attr_reader :player

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM