gpt4 book ai didi

hash - 尝试模拟哈希元素的获取和放置时,RSpec 无法定义单例错误

转载 作者:行者123 更新时间:2023-12-05 01:07:54 25 4
gpt4 key购买 nike

我有一个图书模型,它是一个 ruby​​ 脚本,可将价格分配给程序中提到的某些预定义图书标题。这是书本模型的外观:-

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"

我正在尝试编写一个测试用例来检查每本书的价格输入是否正确。如果价格输入不正确,它应该要求用户重新输入正确的价格。该程序做得很好。但是当我尝试使用 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

你甚至可以 clone this code从 Github 开始尝试这个。我正在使用 Ruby 1.9.3 和 rspec 2.11.0
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

更新问题

对于错误的用户输入,使用以下测试用例,我收到以下错误。我怎样才能正确处理这个?我尝试了几个选项,但它们似乎都失败了。请参阅作为规范片段一部分的每个选项的注释。
 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")
#STDOUT.should == "Price cannot be 0 or a negative integer or in decimal format or alphanumeric. \nPlease input appropriate duration in integer\n"
end


Failures:

1) Book#getprice Incorrect input format should return error message asking user to re input
Failure/Error: 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")
(#<IO:0x00000001c7b298>).puts(any args)
expected: 1 time
received: 0 times
# ./spec/book_spec.rb:40:in `block (3 levels) in <top (required)>'

我真的很感激任何指导如何做到这一点。谢谢你。

最佳答案

如果您使用 --backtrace 标志运行规范,您会看到在 https://github.com/rspec/rspec-mocks/blob/v2.13.0/lib/rspec/mocks/method_double.rb#L140 上引发了错误,其中 rspec-mocks 试图获取被 stub 或模拟的对象的单例类。这适用于大多数类的实例,但规范中有错误。

代码将 gets 发送到 STDIN ,但规范试图在 gets 上 stub book_obj.books["The Last Samurai"] ,当时是 int ,并且您无法从 int 获得单例:

$ irb
1.9.3-p392 :001 > class << 1; self; end
TypeError: can't define singleton
from (irb):1
from /Users/david/.rvm/rubies/ruby-1.9.3-p392/bin/irb:16:in `<main>'

如果我理解正确,您想要进行两个更改。首先,将脚本的最后几行移动到一个单独的文件中,当您运行规范时不会加载该文件,例如bin/books(它可能需要 book.rb 然后添加这些行)。

接下来,删除在 gets 上 stub book_obj.books["The Last Samurai"] 的行,并在调用 gets 的行之前添加一行在 STDIN 上 stub get_prices 的行(这是发生与 STDIN 的交互的时间):
STDIN.stub(:gets) { "40" }
book_obj.get_prices.should_not be_nil

这至少会让你的规范通过。

一般来说,直接处理 STDINSTDOUT 的代码很难在对象级别进行规范,因为像 rspec、minitest 等测试工具都使用 STDOUT 来呈现它们的信息,所以你最终会在贝壳。我建议要么更改设计以将输入/输出流注入(inject) book 类(运行脚本时可以是 STDINSTDOUT,但运行 rspec 时测试 double ),或者使用像 aruba 这样设计的工具指定交互式 shell 脚本。

关于hash - 尝试模拟哈希元素的获取和放置时,RSpec 无法定义单例错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17760803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com