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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

Q&A

解決済

2回答

2356閲覧

Rspecのコントローラー単体テストでActiveRecord::NotNullViolationが発生する

programmingnuoh

総合スコア0

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

保存

保存(save)とは、特定のファイルを、ハードディスク等の外部記憶装置に記録する行為を指します。

0グッド

0クリップ

投稿2021/05/08 11:30

編集2021/05/09 12:26

前提・実現したいこと

この質問で解決したいこと:Rspecでcreateメソッドで保存した値を用いてテストを実行したい

こちらでの質問は初めてのため、質問内容に至らぬ点が多々あるかもしれません。
大変お手数ですが、情報に不備がある場合はご指摘いただけますと幸いです。

開発内容:惣菜投稿サイト。会員情報を登録したユーザーが惣菜を投稿・共有することを目的としたサイト。

エラーが起きている内容:Rspecでの投稿機能のコントローラー単体テスト実装中に、createメソッドで値を保存してテストを実行したいが、データベースのエラーが出てしまう

最終目標:createメソッドで値を保存し、投稿機能のコントローラー単体テストを実行すること

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

1) Delis Controller GET #index indexアクションにリクエストすると正常にレスポンスが返ってくる Failure/Error: @deli = FactoryBot.create(:deli) ActiveRecord::NotNullViolation: Mysql2::Error: Field 'name' doesn't have a default value # ./spec/requests/delis_spec.rb:5:in `block (2 levels) in <top (required)>' # ------------------ # --- Caused by: --- # Mysql2::Error: # Field 'name' doesn't have a default value # ./spec/requests/delis_spec.rb:5:in `block (2 levels) in <top (required)>'

該当のソースコード

delis_spec.rb

ruby

1require 'rails_helper' 2 3RSpec.describe "Delis Controller", type: :request do 4 before do 5 @deli = FactoryBot.create(:deli) 6 sleep(1) 7 end 8 9 describe "GET #index" do 10 it "indexアクションにリクエストすると正常にレスポンスが返ってくる" do 11 get root_path 12 expect(response.status).to eq(200) 13 end 14 15 it 'indexアクションにリクエストするとレスポンスに投稿済みの惣菜名が存在する' do 16 get root_path 17 expect(response.body).to include(@deli.name) 18 end 19 end 20end

delis.rb

ruby

1FactoryBot.define do 2 factory :deli do 3 name {Faker::Food.dish} 4 text {Faker::Lorem.sentence} 5 supermarket_id{rand(1..10)} 6 association :user 7 association :category 8 after(:build) do |deli| 9 deli.image.attach(io: File.open("#{Rails.root}/public/testimage.jpg"), filename:'testimage.jpg') 10 end 11 end 12end

deli.rb(モデルコントローラー記述内容)

ruby

1class Deli < ApplicationRecord 2 3 with_options presence:true do 4 validates :name 5 validates :text 6 validates :supermarket_id 7 validates :image 8 end 9 10 belongs_to :user 11 belongs_to :category 12 has_one_attached :image 13 extend ActiveHash::Associations::ActiveRecordExtensions 14 belongs_to_active_hash :supermarket 15end

delis_controkker.rb(コントローラー記述内容、new/createメソッドのみ記載しています。)

ruby

1class DelisController < ApplicationController 2 3〜前略〜 4 5 def index 6 @delis = Deli.all 7 end 8 9 def new 10 @deli = Deli.new 11 end 12 13 def create 14 @deli = Deli.new(deli_params) 15 if @deli.save 16 redirect_to root_path 17 else 18 render :new 19 end 20 end 21 22〜中略〜 23 24 private 25 def deli_params 26 params.require(:deli).permit(:name, :text, :category_id, :supermarket_id, :image).merge(user_id: current_user.id) 27 end 28end

マイグレーションファイル

ruby

1class CreateDelis < ActiveRecord::Migration[6.0] 2 def change 3 create_table :delis do |t| 4 5 t.string :name, null:false 6 t.text :text, null:false 7 t.integer :supermarket_id, null:false 8 t.references :user, null:false, foreign_key: true 9 t.references :category, null:false, foreign_key: true 10 t.timestamps 11 end 12 end 13end

試したこと

  • エラー文からマイグレーションファイルやコントローラーのパラメーター部分に問題があると仮定し、記述内容を再確認

→確認後テスト結果に変化なし。尚、手動で新規投稿すると投稿が完了し、値が保存できている。
下記の記事を参照
https://qiita.com/divclass123/items/34c4a5a7200238a0589c
https://stackoverflow.com/questions/59644863/activerecordnotnullviolation-mysql2-column-cannot-be-null?answertab=active#tab-top

  • テストコード内でbuildメソッド・saveメソッドと分けて記述を行う

→確認後のテスト結果に変化なし。なぜ二度手間の記述をしたかだが、buildメソッドでの値の生成のみは成功しているため、この方法を試した。

  • FactoryBotによるnameカラムの値の生成を、Fakerを使用せず仮の文字列('test')で試みる

→確認後のテスト結果に変化なし。値の生成には問題なく、あくまで保存に関してデータベースの問題ではないかと考える

補足情報

ruby-version 2.6.5を使用。

長文で読みにくい文章になってしまい大変恐縮ですが、
ご助力いただけますと幸いです。
よろしくお願いいたします。

追記

値の生成についてテストファイル内に記述したところ、テストが成功しました。
そのことから、FactoryBotの記述に問題があるのでは?と考えております。

ruby

1require 'rails_helper' 2 3RSpec.describe "Delis", type: :request do 4 before do 5 @user = User.create(name:'sample', email:"aaa@yahoo.com", password:"sample00", password_confirmation:'sample00') 6 @deli = Deli.create(name:'test', text:'test', category_id:1, supermarket_id:1, user_id:1) 7 end 8 9 describe "GET /delis" do 10 it "indexアクションにリクエストすると正常にレスポンスが返ってくる" do 11 get root_path 12 expect(response.status).to eq(200) 13 end 14 15 it 'indexアクションにリクエストするとレスポンスに投稿済みの惣菜名が存在する' do 16 get root_path 17 expect(response.body).to include(@deli.name) 18 end 19 20 it 'indexアクションにリクエストするとレスポンスに投稿済みの画像が存在する' do 21 22 end 23 24 it 'indexアクションにリクエストするとレスポンスにカテゴリー名が存在する' do 25 get root_path 26 expect(response.body).to include(@deli.category.name) 27 end 28 29 it 'indexアクションにリクエストするとレスポンスに投稿者のユーザー名が存在する' do 30 get root_path 31 expect(response.body).to include(@deli.user.name) 32 end 33 end 34end

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/05/08 13:41

えっと、肝心のindexアクションのコードはどこでしょうか?
programmingnuoh

2021/05/08 14:00

ご確認ありがとうございます。 また、失礼いたしました。 ただいま質問内容のところのコントローラーファイル記述部分にindexアクションの内容を記載いたしました。 何卒よろしくお願いいたします。
guest

回答2

0

そもそも論として、@deli = FactoryBot.create(:deli)indexアクションの検証には全く不要ではないでしょうか。

投稿2021/05/08 14:02

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

programmingnuoh

2021/05/08 14:07

ご回答いただきありがとうございます。 テストコードの内容に記載漏れがあったのですが、indexアクションの検証の中で投稿した内容が表示されているかという確認をしたいためcreateで値の保存をしていたところ、今回のエラーに遭遇いたしました。 質問内容がわかりづらくなっており申し訳ありません。
maisumakun

2021/05/08 14:11

とりあえず、FactoryBot.create(:deli)が失敗しているようですね。 FactoryBot.build(:deli)のデータを確認してみるとどのようになっていますか?
programmingnuoh

2021/05/08 14:13 編集

下記のようになっております => #<Deli:0x00007f919a24eb08 id: nil, name: "Bruschette with Tomato", text: "In reprehenderit quae et.", supermarket_id: 4, user_id: nil, category_id: 1, created_at: nil, updated_at: nil
maisumakun

2021/05/08 14:21

それをsaveしてnameのNOT NULLを食らうのもおかしいですね…もしかしてですけど、テスト環境のマイグレーションを回し忘れているなどはありませんか?
asm

2021/05/08 15:31

> user_id: nil, user_idにもNOT NULLついてるので、こっちはエラー出て当然ですね
programmingnuoh

2021/05/09 00:42

asmさん ご指摘いただきありがとうございます。 buildで生成した場合でもuser_idは付くものなのでしょうか? 自分の過去の制作物等も確認したのですが、どれも生成のときにはuser_idはつかなかったのです。 (そもそもRspecの記述方法が根こそぎ間違っているのでしょうか?)
asm

2021/05/09 01:20

buildを引き継ぐのでuser_idがnilになるかもしれません。 (ただ、category_idと何がちがうのか?が疑問です) save時のsqlをログを探すなりして読み解くしかなさそうですね。
guest

0

自己解決

結論としては、アソシエーションを組んでいたcategoryのFactoryBotの記述内容が間違っていたため、エラーが発生していました。

ruby

1FactoryBot.define do 2 factory :category do 3 name { 'アレンジレシピ' } ← id {1} 4 end 5end 6

idを記述してしまっていました。
nameカラムに値を入れる形で変更したところ、テストが通りました。

maisumakunさん、asmさん、ご助力いただきありがとうございました。

投稿2021/05/09 12:46

programmingnuoh

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問