RailsチュートリアルのテストをRspecで書いてみた[第11章]
はじめに
今回はRspecの学習の一環として、RailsチュートリアルのテストをRspecで書いていきます。
至らない点があるかもしれませんが、その際はコメントにてご指摘をお願いします。
各種バージョン
Ruby 2.7.0
Rails 6.0.3.3
Rspec 3.9
Capybara 3.33.0
Factory_bot_rails 6.1.0
第11章
リスト11.18 アカウント有効化のプレビューメソッド(完成)
spec/mailers/previews/user_mailer_preview.rb class UserMailerPreview < ActionMailer::Preview def account_activation user = User.first user.activation_token = User.new_token UserMailer.account_activation(user) end end
リスト11.20 現在のメールの実装をテストする
spec/mailers/user_mailer_spec.rb require "rails_helper" RSpec.describe UserMailer, type: :mailer do describe "account_activation" do let(:user) { FactoryBot.create(:user) } #account_activationの引数を忘れないこと!! let(:mail) { UserMailer.account_activation(user) } it "renders the headers" do expect(mail.subject).to eq "Account activation" expect(mail.to).to eq([user.email]) expect(mail.from).to eq(["noreply@example.com"]) end it "renders the body" do expect(mail.body.encoded).to match user.name expect(mail.body.encoded).to match user.activation_token # CGIモジュールのescapeメソッドを使用している。 # @が%40に変換される expect(mail.body.encoded).to match CGI.escape(user.email) end end end
Railsチュートリアルにあるuser.activation_token = User.new_tokenは必要ありません。
なぜなら、FactoryBot.createでテストユーザを作成しており、その際に
Userモデルにあるbefore_create :create_activation_digestが実行されるからです。
リスト11.29 Userテスト内の抽象化したauthenticated?メソッド
spec/models/user_spec.rb require 'rails_helper' RSpec.describe User, type: :model do ・・・ # authenticated?のテスト it 'returns false for a user with nil digest' do expect(user.authenticated?(:remember, '')).to be_falsy end end
リスト11.29 ユーザー登録にテストにアカウント有効化を追加する
有効化用のメールを送信するまでのテストを
既存の「users_request_spec.rb」に追加します。
spec/requests/users_request_spec.rb require 'rails_helper' RSpec.describe "Users", type: :request do ・・・ describe "POST /users" do let(:user) { FactoryBot.attributes_for(:user) } it "adds new user with correct signup information and sends an activation email" do aggregate_failures do expect do post users_path, params: { user: user } end.to change(User, :count).by(1) # ここから追加、及び修正しています。 expect(ActionMailer::Base.deliveries.size).to eq(1) expect(response).to redirect_to root_url expect(is_logged_in?).to be_falsy end end end end
次に「account_activations_request_spec.rb」で、アカウント有効化に対してのテストを行います。
また、assignsメソッドは使用せずに書いています。
まずは新しいテストユーザを追加します。
spec/factories/users.rb FactoryBot.define do factory :user do name { "TestUser" } sequence(:email) { |n| "test#{n}@example.com" } password { "foobar" } password_confirmation { "foobar" } activated { true } activated_at { Time.zone.now } trait :admin do admin { true } end # 新しく追加します。 trait :no_activated do activated { false } activated_at { nil } end end end
次に「account_activations_request_spec.rb」にテストを書いていきます。
spec/requests/account_activations_request_spec.rb require 'rails_helper' RSpec.describe "AccountActivations", type: :request do let(:user) { FactoryBot.create(:user, :no_activated) } # 正しいトークンと間違ったemailの場合 context 'when user sends right token and wrong email' do before do get edit_account_activation_path( user.activation_token, email: 'wrong', ) end it "falis login" do expect(is_logged_in?).to be_falsy expect(response).to redirect_to root_url end end # 間違ったトークンと正しいemailの場合 context 'when user sends wrong token and right email' do before do get edit_account_activation_path( 'wrong', email: user.email, ) end it "falis login" do expect(is_logged_in?).to be_falsy expect(response).to redirect_to root_url end end # トークン、emailが両方正しい場合 context 'when user sends right token and right email' do before do get edit_account_activation_path( user.activation_token, email: user.email, ) end it "succeeds login" do expect(is_logged_in?).to be_truthy expect(response).to redirect_to user end end end