質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.22%

RSpecを使用したモデル単体テストコードを実装したい

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 73

noah1111

score 4

前提・実現したいこと

ユーザー(selller)と住所(address_seller)を一緒に登録する機能のモデルのテストコードを実装したいのですが、バリデーションがうまく作用せず
どのように実装したら良いのか悩んでおります。
ローカルで動かしている時はしっかりバリデーションが作用しています。

発生している問題・エラーメッセージ

バリデーションが作用せず、からのデータがあったとしても@〜.valid?でtrueに返されてしまう。

該当のソースコード

spec モデルテストコード
require 'rails_helper'

RSpec.describe AddressSeller, type: :model do
  describe '#create' do
    before do
      @address_seller = FactoryBot.build(:address_seller)
    end

    context '商品購入できるとき' do
      it '全ての項目の入力が存在すれば登録できること' do
        expect(@address_seller).to be_valid
      end
      it '建物名が存在しなくても登録できること' do
        @address_seller.house_number = ""
        expect(@address_seller).to be_valid
      end
    end

    context '商品購入できないとき' do
      it '郵便番号が空では登録できない' do
        @address_seller.postal_code = ''
        @address_seller.valid?
        binding.pry
        expect(@address_seller.errors.full_messages).to include()
      end
    end
  end
end
spec FactoryBot
FactoryBot.define do
  factory :address_seller do
    postal_code { "333-3333" }
    area { '東京' }
    city { "浜田市" }
    block_number { "夕香の塔" }
    house_number { "309-11" }
    phone_number { "11111111111" }
    seller_id { 1 }
  end
end
address_seller モデル
class AddressSeller < ApplicationRecord
  belongs_to :seller, optional: true
  include Addressable
end
concerns
module Addressable
    extend ActiveSupport::Concern

    included do
        with_options presence: true do
            validates :postal_code, format:{with: /\A\d{3}[-]\d{4}\z/}
            validates :area
            validates :city
            validates :block_number
            validates :phone_number, format:{with:/\A\d{11}\z/}
        end
    end
end
devise sellers コントローラー
class Sellers::RegistrationsController < Devise::RegistrationsController
  # before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  # GET /resource/sign_up
  def new
    @seller = Seller.new
  end

  def create
    @seller = Seller.new(sign_up_params)
     unless @seller.valid?
       render :new and return
     end
    session["devise.regist_data"] = {seller: @seller.attributes}
    session["devise.regist_data"][:seller]["password"] = params[:seller][:password]
    @address = @seller.build_address_seller
    render :new_address
  end

  def create_address
    @seller = Seller.new(session["devise.regist_data"]["seller"])
    @address = AddressSeller.new(address_params)
     unless @address.valid?
       render :new_address and return
     end
    @seller.build_address_seller(@address.attributes)
    @seller.save
    session["devise.regist_data"]["seller"].clear
    sign_in(:seller, @seller)
  end

  private

  def address_params
    params.require(:address_seller).permit(:postal_code, :area, :city, :block_number, :phone_number, :house_number)
  end
end

試したこと

binding.pryを記述し、コンソール内でvalid?をしたところtrueと返ってきてしまいました。
concernsの記述を引用していたのでsellerモデルに直接バリデーション を書き込んでみましたがバリデーションは作用しなかったです。
ですのでローカルで確認しましたが、ローカルの方ではしっかりとバリデーションがかかっていました。
sellerのモデルテストコードは問題なく実装できました。

rails cでコンソールを立ち上げ、実際に手打ちでしていくとしっかりバリデーションがかかるのですが
この文章をspecファイルで bundle exec rspec spec/models/address_seller_spec.rb で一連のテストコードを流してしまうとtrueになってしまうようです。

*手入力
[1] pry(main)> address_seller = AddressSeller.new(postal_code: '', area: 'ここ', city: 'ここ', block_number: 'ここ', phone_number: '11111111111')
(0.9ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
=> #<AddressSeller:0x00007faf5adcb980
id: nil,
postal_code: "",
area: "ここ",
city: "ここ",
block_number: "ここ",
house_number: nil,
phone_number: "11111111111",
seller_id: nil,
created_at: nil,
updated_at: nil>
[2] pry(main)> address_seller.valid?
=> false
[3] pry(main)> address_seller.errors.full_messages
=> ["Postal code can't be blank", "Postal code is invalid"]

*binding.pryを記述しbundle exec rspec spec/models/address_seller_spec.rbした
id: nil,
postal_code: "",
area: "ここ",
city: "ここ",
block_number: "ここ",
house_number: nil,
phone_number: "11111111111",
seller_id: nil,
created_at: nil,
updated_at: nil>
[3] pry(#<RSpec::ExampleGroups::AddressSeller::Create::Nested_2>)> address_seller.valid?
=> true

初歩的なことかもしれませんが教えていただけると助かります。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • shinoharat2

    2021/02/24 12:47

    現段階で提示して頂いているコードだと問題なさそうに見えます。
    可能性があるとしたら、spec側にvalid?メソッドをスタブするような処理があるとかですかね……?

    specのコードは貼って頂いたもので全部ですか?
    もし一部の切り抜きなら、切り抜いた部分以外に原因があるかもしれないので、全体のコードを貼ってもらえると何か分かるかも知れません。

    キャンセル

  • noah1111

    2021/02/24 15:11

    コメントありがとうどざいます!
    現在、とても簡略化した文章で、再度試していました


    require 'rails_helper'

    RSpec.describe AddressSeller, type: :model do
    describe 'ユーザー新規登録' do
    it 'nicknameが空では登録できない' do
    address_seller = AddressSeller.new(postal_code: '', area: 'ここ', city: 'ここ', block_number: 'ここ', phone_number: '11111111111')
    address_seller.valid?
    expect(address_seller.errors.full_messages).to include("Postal code can't be blank", "Postal code is invalid")
    end
    end
    end

    こちらになるのですが、こちらでもtrueで返されてしまうのです。

    全てというのは他のモデルテストコードのファイルもでしょうか。
    今回のaddress_sellerに関しましては全て貼らせていただきました。

    キャンセル

  • shinoharat2

    2021/02/27 11:13

    返信遅れてすみません。

    > 全てというのは他のモデルテストコードのファイルもでしょうか。

    address_seller に関するものがすべて、という意味でした。

    > 今回のaddress_sellerに関しましては全て貼らせていただきました。

    そうなのですね。そうするとお手上げです・・・。

    > 現在、とても簡略化した文章で、再度試していました

    念の為確認ですが、簡略化したspecを1件のみ実行しても失敗するんですよね?

    // ファイル名指定で実行する例
    $ bundle exec rspec path/to/address_seller_spec.rb

    キャンセル

  • noah1111

    2021/02/27 16:08

    はい、どうしても失敗してしまいます。。。
    ですので対策法として、concernsの内容をモデルに直接書き込んだら一応バリデーションが作用したのでそのまま今回はいくことにしました。
    今回は丁寧に教えていただきありがとうどざいました

    キャンセル

まだ回答がついていません

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る