如何使用 Rspec 测试控制器中的销毁失败?
How to test destroy failure in controller using Rspec?
我有一个具有以下操作的图书控制器...
def destroy
@book = Book.find(params[:id])
if @book.destroy
redirect_to(books_path)
else
render('delete')
end
end
我能够测试第一个 if 情况,但不能测试 @book.destroy returns 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() return 为假,但它仍然returns true 并测试第一个 if 语句中的代码。我不知道如何覆盖 else 语句中的代码。有什么帮助吗?
谢谢。
您的测试不起作用的主要原因是 Book.find
将从数据库加载记录并创建 class 的新实例,这意味着 #destroy
未被调用您存根的同一个对象。
您需要对 Book.find
方法进行存根,以便 returns 使用存根方法的书籍实例:
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
我有一个具有以下操作的图书控制器...
def destroy
@book = Book.find(params[:id])
if @book.destroy
redirect_to(books_path)
else
render('delete')
end
end
我能够测试第一个 if 情况,但不能测试 @book.destroy returns 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() return 为假,但它仍然returns true 并测试第一个 if 语句中的代码。我不知道如何覆盖 else 语句中的代码。有什么帮助吗?
谢谢。
您的测试不起作用的主要原因是 Book.find
将从数据库加载记录并创建 class 的新实例,这意味着 #destroy
未被调用您存根的同一个对象。
您需要对 Book.find
方法进行存根,以便 returns 使用存根方法的书籍实例:
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