RSpecのフィーチャースペックでメソッドのスタブ化ができない
プロジェクトを管理するサンプルアプリケーションを題材にRSpecの勉強をしています。
サンプルアプリケーションは、プロジェクトを登録することができ、そのプロジェクトは完了済みかどうかのステータス(boolean型のcompleted)を持っています。
プロジェクトの詳細画面には、完了ボタンがあり、完了ボタンを押すと、ステータスが完了済みになります。
この完了ボタンを押すときの、完了処理が失敗したときのフィーチャースペックを書いています。
models/project.rb
class Project < ApplicationRecord
def complete_pj
update_attributes(completed: true)
end
end
controllers/projects_controller.rb
class ProjectsController < ApplicationController
def complete
if @project.complete_pj
redirect_to @project, notice: "Congratulations, this project is complete!"
else
redirect_to @project, alert: "Unable to complete project."
end
end
end
spec/features/projects_spec.rb
require 'rails_helper'
RSpec.feature "Projects", type: :feature do
scenario "ユーザはプロジェクトを完了済みにする(しかし失敗する)" do
# 未完了プロジェクトを持ったユーザを準備する
user = FactoryBot.create(:user)
project = FactoryBot.create(:project, owner: user, completed: false)
# ユーザはログインしている
sign_in user
# ユーザがプロジェクト詳細画面を開く。
visit project_path(project)
# 完了ボタンをクリックする。
click_button "Complete" # → ここでProjectController#completeアクションが呼ばれる
# 完了処理は失敗し、未完了のままとなる。
expect(project.reload.completed).to eq false
end
end
完了ボタンを押すことによりProjectController#completeアクションが呼ばれ、その内部で@project.complete_pjが呼ばれます。この「@project.complete_pj」にfalseを返させたいです。
complete_pjメソッドをスタブ化してfalseを返すようにしてやればいいのでは・・・というのは何となくわかるのですが、どうやってコードを書いたらいいかわかりません。
click_button "Complete"
の前にallow(project).to receive(:complete_pj).and_return(false)
を入れるとパスするのでOKかと思いきや、and_return(true)に変えてもパスするので、そもそもスタブ化がうまくできていないようでした。
宜しくお願いします。