[rspec-users] How to catch the mocked infinite loop behavior and handle it with a rescue block using RSpec

Mohnish J. lists at ruby-forum.com
Sat Jul 20 17:19:37 UTC 2013


I have a Book Model which is a ruby script that assigns prices to
certain predefined Book titles mentioned in the program. I'm using Ruby
1.9.3-p327 and rspec 2.11.0



    #class RspecLoopStop < Exception; end
    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 cannot be 0 or a negative integer or in decimal
format or alphanumeric. \nPlease input appropriate duration 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:#{book_details.books}******\n"


If a user inputs any alphanumeric data or negative number or 0 or
anything having decimals, as per the program the user is asked to enter
only a positive integer for the price of each book. I've tried to mock
this behavior using RSpec.

My current challenge is how to catch the wrong user input, the message
that comes along with and handle it appropriately so that the spec
should pass. I've tried a couple of things but the below spec currently
runs into an infinite loop with input price given in the wrong format.
PFB my spec.

    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 "#getprice" do
        it "Should get the price in the correct format or else return
appropriate error" do
          puts
"\n************************************************************************\n"
          book_obj = @book
          STDIN.stub(:gets) { "40" }
          book_obj.get_prices.should_not be_nil
        end

        it "Incorrect input format should return error message asking
user to re input" do
          puts
"\n************************************************************************\n"
          book_obj = @book
          #STDIN.stub(:gets) { "40abc" }

          #book_obj.get_prices.should be_nil --> adding this line of
code goes into an infinite loop with the error message below
          #Price cannot be 0 or a negative integer or in decimal format
or alphanumeric. \nPlease input appropriate duration in integer\n

          #STDOUT.should_receive(:puts).and_return("Price cannot be 0 or
a negative integer or in decimal format or alphanumeric. \nPlease input
appropriate duration in integer\n")

          #the below two tests fails with syntax error - don't seem that
easy to figure out what's going wrong

          #STDOUT.should_receive("Price cannot be 0 or a negative
integer or in decimal format or alphanumeric. \nPlease input appropriate
duration in integer\n")
          #\n towards the end is as in the third line of input the user
is asked to re enter input in correct format
          #STDOUT.should == "Price cannot be 0 or a negative integer or
in decimal format or alphanumeric. \nPlease input appropriate duration
in integer\n"


          #begin    #didn't work for me
          #  STDIN.stub(:gets) { "40abc" }
          #  book_obj.get_prices.should_raise RspecLoopStop
          #rescue RspecLoopStop
          #  #exit
          #end

          begin
            STDIN.stub(:gets) { "40abc" } #incorrect input prompts user
to re enter price in correct format
            book_obj.get_prices #how to catch the infinite loop as an
exception and exit out of it say using rescue block
          rescue #I guess this won't be called until the exception is
correctly caught
            STDIN.stub(:gets) { "85" }
            book_obj.get_prices.should_not be_nil
          end

        end
      end

    end

Can anyone please point me in the right direction on how can I handle
this correctly. I'm able to mock the user being asked to re enter data
for wrong input. My question is how can I stop that(as per the actual
program logic) upon correct input as part of the spec.

I did try one of the suggestions from [a similar question][1], but it
doesn't seem to be working for me. I could be missing something. The
[code][2] is also available to be cloned from Github. Thank you.


  [1]:
http://stackoverflow.com/questions/5717813/what-is-the-best-practice-when-it-comes-to-testing-infinite-loops
  [2]: https://github.com/boddhisattva/book.git

Attachments:
http://www.ruby-forum.com/attachment/8628/book.rb
http://www.ruby-forum.com/attachment/8629/book_spec.rb


-- 
Posted via http://www.ruby-forum.com/.


More information about the rspec-users mailing list