【rails6】モデル単体テストエラー　ActiveRecord::StatementInvalid: Mysql2::Error: MySQL client is not connected

こんにちは！プログラミング初学者です！
今日はアプリケーションのモデル単体テストコードでのエラー解決について書いていきます

# エラー内容
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'
```

調べていると、原因は下記２つに絞られる様です
・MySQL serverの停止、再起動が原因で今まで使っていた network socket が使えなくなった
・SQL が read_timeout 以内に実行が終わらなかった

参照元
https://abicky.net/2017/09/17/014241/
・・・ありがとうございます！！

私の実行ファイルは行数も少ないので、全てに binding.pry を仕込んでみようと思います

``` spec/models/comment_spec.rb
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 内を書き換えてみます

``` spec/models/comment_spec.rb
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秒休憩させて次の処理をさせる**
そんなイメージを持っていれば良いのではないでしょうか？？

みなさんも解決できましたか？
さてさて、私は先に進むとします:runner: