👋
RSpecで空配列が欲しいのに空文字が混入する
ハコベル開発チームの坂東です。チームでモブプロをしながらRSpecを書いている最中に遭遇した挙動に困惑したので、備忘録も兼ねて記します。
環境
- Rails: 7.0.8
- RSpec: 6.1.2
RSpecで空配列が欲しいのに空文字が混入する
RSpecでリクエストスペックを書く際、空の配列をPOSTリクエストのパラメータとして送信すると、Railsがこれを空文字として解釈するケースがあります。
通らないテスト例
# spec/requests/posts_spec.rb
require 'rails_helper'
RSpec.describe "Posts", type: :request do
describe "POST /posts" do
context "when sending an empty array" do
it "interprets the empty array as an empty array" do
post '/posts', params: { ids: [] }
# 出力されるparamsを確認
puts request.params[:ids] # 期待: [], 実際: [""]
expect(request.params[:ids]).to eq([])
end
end
end
end
このテストは、空の配列[]
を送信したつもりが、空文字列の配列[""]
として解釈されてしまうため、失敗します。
原因と解決方法
この問題は、RspecがデフォルトのContent-Typeとしてapplication/x-www-form-urlencoded
形式を想定していることに関係しています。
このContent -Typeの場合、空の配列は空文字列の配列として解釈されます。
この問題を回避するためには、リクエストの形式をJSONとして明示的に指定します。以下のように記述することで、空配列を正しく送信できます。
post '/posts', params: { ids: [] }, as: :json
修正後のテスト例
# spec/requests/posts_spec.rb
require 'rails_helper'
RSpec.describe "Posts", type: :request do
describe "POST /posts" do
context "when sending an empty array" do
it "interprets the empty array as an empty array" do
post '/posts', params: { ids: [] }, as: :json
# 出力されるparamsを確認
puts request.params[:ids] # 期待: [], 実際: []
expect(request.params[:ids]).to eq([])
end
end
end
end
この方法により、空配列が正しく送信され、期待通りの動作が得られます。
終わりに
以下でも述べられている通り、これは昔からハマる人がいる挙動のようです。
これはバグではなく、RSpecのデフォルトの挙動によるものです。いざ遭遇すると原因が特定しづらいので、RSpecでテストを書く際は、このことを頭に入れておくと良いでしょう。
「物流の次を発明する」をミッションに物流のシェアリングプラットフォームを運営する、ハコベル株式会社 開発チームのテックブログです! 【エンジニア積極採用中】t.hacobell.com/blog/career
Discussion