woodman0224
@woodman0224 (林 正)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Railsのテスト(RSpec)をパスしたい

解決したいこと

RSpecで下記のテストがエラーになるのでパスしたい

it 'パスワードが存在すること' do
    @user.password = ""
    expect(@user).to be_invalid
end

事前にFactoryBotで@userにデータを挿入しています。

自分で試したこと

原因はuser.passwordに空の値を入れても反映されていない事です。
user.password_confirmationや他のカラムの場合は空の値が反映されています。
user.passwordに値を代入できない理由がわかりません泣
どなたかご教授お願いします😭

irb(main):030:0> user.password
=> "password"
irb(main):031:0> user.password = ""
=> ""
irb(main):032:0> user.password
=> "password"
irb(main):033:0> 
                    

補足

userモデルはこのようになっています。

create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.string "name", null: false
    t.string "email", null: false
    t.string "password_digest"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
end

バリデーションは以下の通りです。※追記あり

#user.rb
has_secure_password
validates :name, presence: true, length: { maximum: 10 }
validates :email, presence: true, uniqueness: true
validates :password, presence: true, length: { in: 8..20 }
#検証のため追加
validates :password_confirmation, presence: true, length: { in: 8..20 }

factorybotで作成したデータです


FactoryBot.define do
  factory :user do
    name { "テストユーザ" }
    email { "test@example.com" }
    password { "password" }
    password_confirmation { "password"}
    coment { "テスト" }
  end
end

使用状況はこのようになっています。

#user_spec.rb



before do
    @user = FactoryBot.build(:user)
end

it 'パスワードが存在すること' do
    @user[:password] = ""
    expect(@user).to be_invalid
end

ちなみにこの他のカラムに関してのテストは正常にパスされています。

it '名前が存在すること' do
    @user.name = ""
    expect(@user).to be_invalid
end

it 'メールアドレスが存在すること' do
    @user.email = ""
    expect(@user).to be_invalid
end

it 'パスワード(確認)が存在すること' do
    @user.password_confirmation = ""
    expect(@user).to be_invalid
end

解決済み

結局なぜこの方法だと正常に動かないのかは突き止めることが出来ませんでしたが、目的であるテストをパスすることはできましたのでその方法を記載しておきます!

#user_spec.rb



before do
    @user = FactoryBot.build(:user)
end

it 'パスワードが存在すること' do
    @user = FactoryBot.build(:user, password: "")
    expect(@user).to be_valid
end

テスト内でデータをオーバーライドしました!
インスタンス変数である必要は無いのですが、他のテストとの統一感を出すために@userという記述にしています。

コメントをくださった方々には大変感謝です!ありがとうございました!!🙇‍♂️

0

2Answer

Comments

  1. @woodman0224

    Questioner

    コメントありがとうございます!
    deviceは使用していません!
    補足に追加しました!
  2. なんでしょうね
    FactoryBot のコードとその利用部分のコードまで載せてみませんか?
  3. @woodman0224

    Questioner

    返信ありがとうございます!
    また補足に追加しました。自分もなぜ効かないのか全く検討もつきません。。
  4. has_secure_passwordの仕様かもしれないですね

    @user.update!(password: "") で例外が発生することを試すテストに変えても良いかもしれません
  5. @woodman0224

    Questioner

    返信ありがとうございます!
    やはりですか!自分も他に思い当たることがないのでそうなのではないかと思っていました!ただconfirmationの場合だとパスしますし、調べてもそういった内容の記事を見つけれずにいたので、同じ意見を持つ人がいてくれただけで前に進めそうです!笑
    おっしゃられているように違うやり方で試してみようと思います!ありがとうございました!🙇‍♂️

Comments

  1. @woodman0224

    Questioner

    コメントありがとうございます!
    値の変更はできます。user.password = "aaaaaaaa"などした場合には改めてuser.passwordを表示すると"aaaaaaaa"で表示されます!
    空の値を入れるときだけ反映されていない状態なんです😭

    また教えていただいたやり方で試しましたら今度は ActiveModel::MissingAttributeError と出てしまいました。
  2. あ、これはしっかりバリデート設定されてるせいですね。
    8文字以上20文字以下のキーワードしか受け入れないようになっています。

    空文字で上書きできるようになるか確かめたい場合は、設定の、8を0に変更して見るといいと思います。

    validates :password, presence: true, length: { in: 8..20 }

    これが正しい挙動なので、発想を変えて「空文字やその他不適切な文字列で上書きされないこと(つまり上書きしようとしても変更されておらず、かつvalidであること)」をテストすればいいのでは。
  3. @woodman0224

    Questioner

    返信ありがとうございます!
    補足に追記したのですが、password_confimationにも同じバリデーションを加えたんですが、そちらはパスするみたいで。ですので他にも何か理由がありそうなんです、それがわからなくて😢

    なるほどですね!できないなら根本から変えてしまえばですね!
    解決しなかった場合はおっしゃられているように他の発想でテストをしてみようと思います!
  4. @woodman0224

    Questioner

    返信ありがとうございます!
    オーバーライドで出来ました!ずっと再代入で考えてたのがいけなかったです。勉強になりました!
    記事を紹介していただき感謝します!🙇‍♂️

Your answer might help someone💌