Railsのrspecのrequest specについて
上記の記事にあるように、Rails 5以降ではrails-controller-testing gemをアプリケーションに追加することは推奨されておらず、RSpecコアチームはrequest specsを書くことを推奨しています。
その理由として、request specでは、単一のcontroller actionをテストしつつ、さらにcontroller specとは異なり、router、middleware、rackのrequestとresponseが含まれることになります。
これにより、書いているテストがより実際のリクエストに近くなり、controller testにありがちな問題を回避することができます。
Rails 5ではRails 4のrequest specやcontroller specに比べてかなりの高速化も行われています。
このように、controller specはよりrequest specを書くことがRails 5以降のデファクトとなっています。
GitHub - rspec/rspec-rails: RSpec for Rails 5+
request spec - Request specs - RSpec Rails - RSpec - Relish
request specの使用
rspec-railsを使った場合、specのtypeをtop-levelのdescribeで指定します。
RSpec.describe User, type: :request do
requestを指定することで、ActionDispatch::IntegrationTestに相当することになります。
この中でHTTP requestをシュミレートする get
post
patch
put
delete
head
メソッドを使うことになります。
controller specでも同じようなメソッドを使うことになりますが、呼び出されたメソッドが実行するものが違います。
実装は下記になります。
この中で、 Rack::Test::Session
が使われており、Rails appではなく、Rack appとしてリクエストを処理するようになっています。
request specはRackのレイヤーまでを網羅したテストとなっています。
ちょっとハマった点
rack appに対するリクエストを組み立てテストを行うのですが、Rack::Test:Session#requestの実装が少し色々やりすぎててハマりました
このなかで、specで定義したparamsをURL-encoded form dataにエンコードを自動的に行なっているので、テストもとでencodeすると二重でencodeされることになります。
こういった処理をどこまでやるかの判断は難しいですが、自動的に行われることは意識しておいていいかなと思います。