controllerのテスト
controllerにリクエストを送って、想定したレスポンス(httpのステータス)が返ってくるかを確認する(request spec)
controllerの役割を果たせているか確認する
今回は、getリクエストとpostリクエストについてそれぞれテストをしてみる
- 確認したいことを決める
今回は「リクエストを送って、200や正しいレスポンスが返ってくるか」確認したい - リクエストを送る(ダミーデータみたいなもの)
- 200ステータスを確認&レスポンスを確認
- 確認したいことを決める
今回は「リクエストを送って、記事が保存されるか」確認したい - リクエストを送る(ダミーデータみたいなもの)
- postしたパラメーターと、保存された内容が一致しているか確認する
今回はarticles controllerのテストを行う
実際に書いてみる(getリクエスト)
indexにレスポンスを送り、正しいレスポンスが返ってくるか確認したい
def index
@articles = Article.all
end
今回はターミナルからファイルを作ってみる↓
rails g rspec:request article
#=> create spec/requests/articles_spec.rbすると、spec/requests/articles_spec.rbのファイルが出来上がる↓
require 'rails_helper'
RSpec.describe "Articles", type: :request do
describe "GET /articles" do
it "works! (now write some real specs)" do
get articles_path
expect(response).to have_http_status(200)
end
end
end↑を↓に書き換える
'GET /articles'に対して、‘200ステータスが返ってくる’かどうか確認したい
require 'rails_helper'
RSpec.describe 'Articles', type: :request do
describe 'GET /articles' do
it '200ステータスが返ってくる' do
get articles_path
expect(response).to have_http_status(200)
end
end
endit以降は‘確認したい内容’を入れる
ダブルクォーテーションはシングルクォーテーションに変えておく(ほかと統一させる)
get articles_path
→getというメソットのおかげで、articles_pathにリクエストを送ることができる
expect(response).to have_http_status(200)
→httpステータスが「200」のresponseが返ってくればokという意味になる
これらはrspecの特殊な書き方だったりする
今の状態でリクエストを送っても通ることは通る
ただ、本当に検証したいのは「記事がある状態でリクエストが通るかどうか」
記事のない状態で検証しても意味がない・・・
記事を用意した状態で、レスポンスが返ってくるのか検証する
RSpec.describe 'Articles', type: :request do
let!(:user) { create(:user) }
let!(:articles) { create_list(:article, 3, user: user) }let!(:user) { create(:user) }
→記事を作るために、まずはuserを作成する
記事を複数作るのでarticlesとし、creat_listを使う
(:articleを作ること、3記事作ること、先ほど作った:userと紐づけること)を記載する
bundle exec rspec spec/requests/articles_spec.rb成功!

この「・」が緑→テストが通った、赤→テストは失敗という意味
実際に書いてみる(postリクエスト)
「記事が保存されているか」を確認したい
def create
@article = current_user.articles.build(article_params)
if @article.save
redirect_to article_path(@article),
notice: '保存できました'
else
flash.now[:error] = '保存に失敗しました'
render :new
end
endarticles_controller.rbのcreateの部分はこちら↑
記事を作成後、redirect_toしている
redirect_toのときは「200」じゃなくて、「302」が返ってくる
ただ、「redirect_to=記事が保存できている」わけではない
(保存されてなくてもredirect_toされることがある)
なので、「200」「302」が返ってくるかではなく、記事が保存されているかを確認できるようにする
describe 'POST /articles' do
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
end
endpostするときはパラメーターを指定しないといけない
article_paramsとしたとき、attributes_for(:article)を使うと↓の内容でいい感じにパラメーターを作ってくれる

attributes_forは、factory_botで用意されている便利なメソッドのひとつ
これでリクエストを送ると、問題なくステータス「302」が返ってくるようになる
次は、「記事が保存されているか」を確認する方法を考える
describe 'POST /articles' do
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
expect(Article.last.title).to eq(article_params[:title])
expect(Article.last.content).to eq(article_params[:content])
end
endパラメーターで送ったarticle_paramsの中身=最後に保存された記事の中身
以下が一致していれば、記事は保存できていることがわかる!
Article.last.title=article_params[:title]Article.last.content=article_params[:content]
Article.last.contentでは、contentの本文だけじゃなく、インスタンスとして返ってきてしまう

Article.last.content.body.to_plain_textコンソール画面で上記のとおり入力してみる

文字列だけ取れた!
ひとまず完成したコードはこちら↓
describe 'POST /articles' do
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
expect(Article.last.title).to eq(article_params[:title])
expect(Article.last.content.to_plain_text).to eq(article_params[:content])
end
endこの状態でテストを実行しても失敗する
現状、ログインしていないからcreateが出来ず、失敗する
deviceにはsign_inというメソッドが用意されている
あとはuserと指定してしまえばログイン状態を作ることができる(簡単!)
describe 'POST /articles' do
context 'ログインしている場合' do
before do
sign_in user
end
it '記事が保存される' do
article_params = attributes_for(:article)
post articles_path({article: article_params})
expect(response).to have_http_status(302)
expect(Article.last.title).to eq(article_params[:title])
expect(Article.last.content.to_plain_text).to eq(article_params[:content])
end
end
endrspecでdeviceの機能を使うためには、rspecに設定をする必要がある(今のままでは使えない)
spec/rails_helper.rbにFactoryBotの設定を書いたように、Deviseのincludeについても記載する
config.include FactoryBot::Syntax::Methods
config.include Devise::Test::IntegrationHelpers, type: :request「request specでDeviceをインストールします」という意味になる
これで、ログインした状態でリクエストを送ることができる
bundle exec rspec spec/requests/articles_spec.rb成功!!

#DAY14

