现有的Ruby代码:
def book_details
book_count = Book.count
while (book_count > 1)
# Do something
end
end
我想写一个rspec测试用例,它在book_details函数中设置book_count值。可能吗?如果是,怎么样?
到目前为止,我所尝试的是:
it 'Should return 1 book details only' do
allow(Model).to receive(book_count).and_return(1)
# Do something
end
但是这给#n / #p>提供了错误'未定义的局部变量或方法`book_count'
答案 0 :(得分:0)
让我们说,book_count = 1000是红宝石代码,你想用rspec将它重置为10,然后下面就可以了:
allow(Book).to receive(:count).and_return(10)
以上将根据您对rspec的期望进行计数。
另外,具体而言,rspec contexts
rspec
是针对methods
编写的,而不是针对local variables
。
因此,rspec
中的测试方法期望。
以下是rspec
的简单method
示例:
class Book
def book_details
book_count = Book.count
while (book_count > 1)
puts 'Book name'
end
end
end
describe 'Books' do
describe '#book_details' do
context 'when Books are less than one' do
it 'should not return book details' do
book_details.should eq 0
book_details.should_not eq 'Book name'
end
end
context 'when Books are more than one' do
before do
FactoryGirl.create(:book)
end
it 'should return book details' do
book_details.should_not eq 0
book_details.should eq 'Book name'
end
end
end
end
答案 1 :(得分:0)
答案基本上是:不要。
如果您觉得需要在方法中间覆盖变量,那么您做错了;该方法责任太多,需要分解。
在这种情况下,让测试工作的一种快捷方式是:
allow(Book).to receive(:count).once.and_return(1)
或者,稍微更简洁的方法是将该调用提取到一个新方法中,因此您只能将您所拥有的行为隐藏起来" - 类似于:
class Foo
def book_details
while (book_count > 1)
# Do something
end
end
def book_count
Book.count
end
end
# In your test:
let(:foo) { Foo.new }
allow(foo).to receive(:book_count).once.and_return(1)
...但事实上,你应该真正在这里做什么,理想情况下,正确地测试方法,就是不要嘲笑任何东西!由于您的代码与数据库交互,因此您的测试应为代码创建真实记录以进行交互:
# Using FactoryBot, for example:
let!(:books) { create_list(:book, 5) }
答案 2 :(得分:0)
Book.stub(:count).and_return(10)