RSpec can't define singleton error when trying to mock gets and puts for Hash Elements


#1

I have a Book Model which is a ruby script that assigns prices to
certain predefined Book titles mentioned in the program. Here’s how the
book model looks:-

class Book

  attr_accessor :books
  def initialize books
    puts "Welcome to setting book price program"
    @books = books
  end

  def get_prices
    puts "Please enter appropriate price for each book item:-"
    count = 0
    @books = @books.inject({}) { |hash, book|
      print "#{book.first}: "
      price = STDIN.gets.chomp
      while (price !~ /^[1-9]\d*$/ && price != "second hand")
        puts "Price can't be 0 or a negative integer or in decimal

format or alphanumeric. \nPlease input appropriate price in integer"
price = STDIN.gets.chomp #gets.chomp - throws error
end
price == “second hand” ? price = “100” : price #takes a
default price
hash[book.first] = price.to_i
hash
}
end

end

books = {"The Last Samurai" => nil,
         "Ruby Cookbook" =>  nil,
         "Rails Recipes" =>  nil,
         "Agile Development with Rails" =>  nil,
         "Harry Potter and the Deathly Hallows" =>  nil}


book_details = Book.new(books)
book_details.get_prices
puts "\n*******Books Details:#{book_details.books}******\n"

I’m trying to write a test case that checks for correct input of price
for each book item. If the price is entered inappropriately, it should
ask the user to re enter the price correctly. The program does this
fine. But I’m facing difficulties when I’m trying to mock this behavior
using RSpec.

require 'spec_helper'

describe Book do

  before :each do
    books = {"The Last Samurai" => nil,
         "Ruby Cookbook" =>  nil,
         "Rails Recipes" =>  nil,
         "Agile Development with Rails" =>  nil,
         "Harry Potter and the Deathly Hallows" =>  nil}
    @book = Book.new(books)
  end

  describe "#new" do
    it "Should be an instance of the Book" do
      @book.should be_an_instance_of Book
    end
  end

  describe "#getprice" do
    it "Should get the price in the correct format or else return

appropriate error" do
puts
“\n************************************************************************\n”
book_obj = @book
STDOUT.should_receive(:puts).and_return(“Welcome to setting
book price program”)
book_obj.get_prices.should_not be_nil
book_obj.books[“The Last Samurai”].stub!(:gets) {“40”} #trying
to set the value for one book using Hash
book_obj.books[“The Last Samurai”].should == 40 #verifying the
value set for a particular key is accurate
end
end

end

You can even clone this code(https://github.com/boddhisattva/book) from
Github to try this from your end. I’m using Ruby 1.9.3 and rspec 2.11.0.
I’ve also attached all the required ruby scripts in this forum post to
test this.

The error that I'm getting currently is:-

Failures:

  1) Book#getprice Should get the price in the correct format or

else return appropriate error
Failure/Error: book_obj.books[“The Last Samurai”].stub!(:gets)
{“40”} #trying to set the value for one book using Hash
TypeError:
can’t define singleton
# ./spec/book_spec.rb:31:in `block (3 levels) in <top
(required)>’

Finished in 7.61 seconds
2 examples, 1 failure

Failed examples:

rspec ./spec/book_spec.rb:21 # Book#getprice Should get the price in

the correct format or else return appropriate error

I would really appreciate any guidance how to get this right. Thank you.