こんにちは!プログラミング初学者です!
今日はアプリケーションのモデル単体テストコードでのエラー解決について書いていきます
エラー内容
ActiveRecord::StatementInvalid: Mysql2::Error: MySQL client is not connected
エラー画面は以下の通りです
% bundle exec rspec spec/models/comment_spec.rb
Comment
記事へのコメント機能
コメントが投稿できるとき
フォームに正しく入力すれば投稿できる
コメントが投稿できないとき
コメントが空欄では投稿できない (FAILED - 1)
ユーザーid(user_id)が空では投稿できない (FAILED - 2)
記事id(article_id)が空では投稿できない (FAILED - 3)
Failures:
1) Comment 記事へのコメント機能 コメントが投稿できないとき コメントが空欄では投稿できない
Failure/Error: _query(sql, @query_options.merge(options))
ActiveRecord::StatementInvalid:
Mysql2::Error::ConnectionError: Lost connection to MySQL server during query
# 見にくくなるので省略 #
# Showing full backtrace because every line was filtered out.
# See docs for RSpec::Configuration#backtrace_exclusion_patterns and
# RSpec::Configuration#backtrace_inclusion_patterns for more information.
# ------------------
# --- Caused by: ---
# Mysql2::Error::ConnectionError:
# Lost connection to MySQL server during query
# /Users/私の名前/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/client.rb:131:in `_query'
調べていると、原因は下記2つに絞られる様です
・MySQL serverの停止、再起動が原因で今まで使っていた network socket が使えなくなった
・SQL が read_timeout 以内に実行が終わらなかった
参照元
https://abicky.net/2017/09/17/014241/
・・・ありがとうございます!!
私の実行ファイルは行数も少ないので、全てに binding.pry を仕込んでみようと思います
RSpec.describe Comment, type: :model do
before do
@user = FactoryBot.create(:user)
@article = FactoryBot.create(:article)
@comment_user = FactoryBot.create(:user)
@comment = FactoryBot.build(:comment, user_id: @comment_user.id, article_id: @article.id)
end
describe '記事へのコメント機能' do
context 'コメントが投稿できるとき' do
it 'フォームに正しく入力すれば投稿できる' do
expect(@comment).to be_valid
end
end
context 'コメントが投稿できないとき' do
it 'コメントが空欄では投稿できない' do
@comment.comment = ''
@comment.valid?
binding.pry
expect(@comment.errors.full_messages).to include('Commentを入力してください')
end
it 'ユーザーid(user_id)が空では投稿できない' do
@comment.user_id = nil
@comment.valid?
binding.pry
expect(@comment.errors.full_messages).to include('Userを入力してください')
end
it '記事id(article_id)が空では投稿できない' do
@comment.article_id = nil
@comment.valid?
binding.pry
expect(@comment.errors.full_messages).to include('Articleを入力してください')
end
end
end
end
% bundle exec rspec spec/models/comment_spec.rb
Comment
記事へのコメント機能
コメントが投稿できるとき
フォームに正しく入力すれば投稿できる
コメントが投稿できないとき
From: /Users/私/projects/アプリ/spec/models/comment_spec.rb:22 :
17:
18: context 'コメントが投稿できないとき' do
19: it 'コメントが空欄では投稿できない' do
20: @comment.comment = ''
21: @comment.valid?
=> 22: binding.pry
23: expect(@comment.errors.full_messages).to include('Commentを入力してください')
24: end
25: it 'ユーザーid(user_id)が空では投稿できない' do
26: @comment.user_id = nil
27: @comment.valid?
[1] pry(#<RSpec::ExampleGroups::Comment::Nested::Nested_2>)> exit
コメントが空欄では投稿できない
From: /Users/私/projects/アプリ/spec/models/comment_spec.rb:28 :
23: expect(@comment.errors.full_messages).to include('Commentを入力してください')
24: end
25: it 'ユーザーid(user_id)が空では投稿できない' do
26: @comment.user_id = nil
27: @comment.valid?
=> 28: binding.pry
29: expect(@comment.errors.full_messages).to include('Userを入力してください')
30: end
31: it '記事id(article_id)が空では投稿できない' do
32: @comment.article_id = nil
33: @comment.valid?
[1] pry(#<RSpec::ExampleGroups::Comment::Nested::Nested_2>)> exit
ユーザーid(user_id)が空では投稿できない
From: /Users/私/projects/アプリ/spec/models/comment_spec.rb:34 :
29: expect(@comment.errors.full_messages).to include('Userを入力してください')
30: end
31: it '記事id(article_id)が空では投稿できない' do
32: @comment.article_id = nil
33: @comment.valid?
=> 34: binding.pry
35: expect(@comment.errors.full_messages).to include('Articleを入力してください')
36: end
37: end
38: end
39: end
[1] pry(#<RSpec::ExampleGroups::Comment::Nested::Nested_2>)> exit
記事id(article_id)が空では投稿できない
Finished in 4.98 seconds (files took 1.31 seconds to load)
4 examples, 0 failures
問題なく通りました!
では、 binding.pry を削除して、
before do 内を書き換えてみます
RSpec.describe Comment, type: :model do
before do
@user = FactoryBot.create(:user)
@article = FactoryBot.create(:article)
@comment_user = FactoryBot.create(:user)
@comment = FactoryBot.build(:comment, user_id: @comment_user.id, article_id: @article.id)
sleep(0.1) # ここを追加
end
# 以下の文章は binding.pry のみを削除してください。それ以外は何も変更しません
では…いざターミナルで実行!!
% bundle exec rspec spec/models/comment_spec.rb
Comment
記事へのコメント機能
コメントが投稿できるとき
フォームに正しく入力すれば投稿できる
コメントが投稿できないとき
コメントが空欄では投稿できない
ユーザーid(user_id)が空では投稿できない
記事id(article_id)が空では投稿できない
Finished in 0.50371 seconds (files took 1.31 seconds to load)
4 examples, 0 failures
問題なく終了できました〜
この sleep(0.1)ですが、
引数に秒数を渡すことによって、その秒数分処理を停止することができます
ms(ミリ秒)の場合は上記の様に引数へ(0.1)や(0.01)と記載すればOKです。
今回は連続した処理で、「SQL が read_timeout 以内に間に合わなかった」と推測します
一つの処理が終わったら0.1秒休憩させて次の処理をさせる
そんなイメージを持っていれば良いのではないでしょうか??
みなさんも解決できましたか?
さてさて、私は先に進むとします