CubicLouve

Spring_MTの技術ブログ

Railsのrspecのrequest specについて

rspec.info

上記の記事にあるように、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に相当することになります。

api.rubyonrails.org

この中でHTTP requestをシュミレートする get post patch put delete head メソッドを使うことになります。

controller specでも同じようなメソッドを使うことになりますが、呼び出されたメソッドが実行するものが違います。

実装は下記になります。

github.com

この中で、 Rack::Test::Session が使われており、Rails appではなく、Rack appとしてリクエストを処理するようになっています。

github.com

request specはRackのレイヤーまでを網羅したテストとなっています。

ちょっとハマった点

rack appに対するリクエストを組み立てテストを行うのですが、Rack::Test:Session#requestの実装が少し色々やりすぎててハマりました

github.com

このなかで、specで定義したparamsをURL-encoded form dataにエンコードを自動的に行なっているので、テストもとでencodeすると二重でencodeされることになります。

こういった処理をどこまでやるかの判断は難しいですが、自動的に行われることは意識しておいていいかなと思います。