如何使用Rspec测试控制器中的破坏故障



我有一个图书控制器,具有以下操作。。。

def destroy
@book = Book.find(params[:id])
if @book.destroy
redirect_to(books_path)
else
render('delete')
end
end

我可以测试第一个if情况,但不能测试@book.destroy返回false的情况。我的问题是——我如何让@book.destroy失败?我想写一个rspec测试来覆盖这种情况。

describe "destroy" do
before(:context) do
@book = create(:book)
end
context "failing the destroy function" do
it "renders delete" do
allow(@book).to receive(:destroy).and_return(false)
delete :destroy, params: { id: @book.id }
expect(response).to render_template(:delete)
end
end
end

我试着写上面的想法,allow(@book(.to receive(:destroy(.and_return(true(会使destroy((返回false,但它仍然返回true,并在第一个if语句中测试代码。我不知道如何在else语句中覆盖代码。请帮忙吗?

谢谢。

测试不起作用的主要原因是Book.find将从数据库加载记录并创建该类的新实例,这意味着#destroy不会在您已存根的同一对象上被调用。

您需要存根Book.find方法,以便它使用存根方法返回图书实例:

describe "destroy" do
context "failing the destroy function" do
let(:book) { build_stubbed(:book) } # use let instead of ivars
# don't use before :context unless you actually 
# have a real reason. You should strive to have 
# each example setup/teardown on their own 
before do
allow(book).to receive(:destroy).and_return(false)
allow(Book).to receive(:find).and_return(book)
end 
it "renders delete" do
delete :destroy, params: { id: book.id }
expect(response).to render_template(:delete)
end
end
end

最新更新