Rails統合テストでDRb::DRbRemoteErrorにハマった話

<h1>前提</h1>
RailsチュートリアルにDockerを使い、学習を進めています。

<h1>開発環境</h1>
Ruby:3.0.2
rails:6.0.4

<h1>発生したエラー</h1>
<h3>5.3.4 リンクのテスト</h3>
統合テストを使うと、アプリケーションの動作を細かくてテストすることができる
site_layoutというテストのテンプレートを生成

```ターミナル.
$ docker-compose exec web bundle exec rails generate integration_test site_layout
      invoke  test_unit
      create    test/integration/site_layout_test.rb
```
リスト 5.32
assert_templateメソッドを使って、Homeページが正しいビューを描画しているか確かめる

```test/integration/site_layout_test.rb
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
  end
end
```
リスト 5.33
統合テストが通る確認しようとしたところ次のようなエラー

```ターミナル.
$ docker-compose exec web bundle exec rails test:integration
Started with run options --seed 57511

ERROR["test_layout_links", #<Minitest::Reporters::Suite:0x0000aaaad715fa40 @name="SiteLayoutTest">, 0.205297333013732]
 test_layout_links#SiteLayoutTest (0.21s)
Minitest::UnexpectedError:         DRb::DRbRemoteError: expecting <"static_pages/home"> but rendering with <["rescues/blocked_host", "rescues/layout"]> (Minitest::Assertion)
            test/integration/site_layout_test.rb:7:in `block in <class:SiteLayoutTest>'

  1/1: [============================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.24128s
1 tests, 1 assertions, 0 failures, 1 errors, 0 skip
```


```but rendering with <["rescues/blocked_host", "rescues/layout"]>```
と出ていたので調べてみると、エラーの原因は、Rails 6.0からの仕様変更のようです。

https://www.tmp1024.com/solve-blocked-host-of-rails/

<h1>解決策①</h1>
```$ rails test:integration```が実行されるときに、テストはexample.comへアクセスしているよう.
デフォルトだと、開発環境ではexample.comへのアクセスは許可されていない

```config/enviroments/development.rb
Rails.application.configure do
  #省略
  config.hosts << "www.example.com"
  #省略
end
```

を追加することによって、開発環境でexample.comへのアクセスを許可することにより、とりあえずはテストが通る

```ターミナル.
$ docker-compose exec web bundle exec rails test:integration
Started with run options --seed 41448

development=---=---=---=---=---=---=---=---=---=---=---=---=---=---=--] 0% Time: 00:00:00,  ETA: ??:??:??
  1/1: [============================================================] 100% Time: 00:00:00, Time: 00:00:00

Finished in 0.98599s
1 tests, 5 assertions, 0 failures, 0 errors, 0 ski
```
通った

<h1>解決策②</h1>
しかし本来テストは開発環境ではなくテスト環境で行うもの
解決策①では、通ったものの「テストが開発環境で実行されてしまう」という根本的な解決になっていない
私のdocker-compose.ymlには、RAILS_ENVの値としてdevelopmentが固定されているので、テスト実行時にテスト環境を使うことができなかった
なので、RAILS_ENVの値を空にすることにより、根本解決となる

```docker-compose.yml
    ...略
    web:
        build: .
        command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
        volumes: 
            - ./src:/app
        ports:
            - "3000:3000"
        environment:
            #developmentを削除
            RAILS_ENV:
        depends_on:
            - db
```
```ターミナル.
$ docker-compose stop

本当は$ docker-compose run --rm --service-ports web で起動させた方がいいみたいです
$ docker-compose up -d

$ docker-compose exec web bundle exec rails test:integratio
Started with run options --seed 34526

  1/1: [============================================================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.05303s
1 tests, 5 assertions, 0 failures, 0 errors, 0 skips
```

通った
（解決策①で追加したexample.comへのアクセスを許可をするコードを消しても通る）

<h1>補足</h1>

test/integration/site_layout_test.rb に```puts ENV["RAILS_ENV"]```を追加することで
```test```と```development```どちらがコンソールに表示されるか確認できる
テストの動作検証時でもputsデバックは便利

```test/integration/site_layout_test.rb
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest

  test "layout links" do
    get root_path
    puts ENV["RAILS_ENV"]
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
  end
end
```

```ターミナル.
$ docker-compose exec web bundle exec rails test:integration
Started with run options --seed 21354

test: [=---=---=---=---=---=---=---=---=---=---=---=---=---=---=---=--] 0% Time: 00:00:00,  ETA: ??:??:??
  1/1: [============================================================] 100% Time: 00:00:01, Time: 00:00:01

Finished in 1.20476s
1 tests, 5 assertions, 0 failures, 0 errors, 0 skips
```
↑テスト環境が使われていることがわかる


皆さんに感謝です
何かご指摘やアドバイスなどあれば、ぜひよろしくお願いします