Coerce stream name to String in test adapter accessors
テストアダプターがブロードキャストを取得する際に、チャネル名を文字列に統一しないため、シンボルで指定したストリームが正しく検出されず、assert_no_broadcasts が実際のレグレッションを見逃す問題を解消しました。
背景
テスト実行時に シンボル でストリーム名を指定することは慣例的に行われていましたが、ActionCable::Server::Broadcasting では書き込み時に String(broadcasting) で文字列化して保存していました。SubscriptionAdapter::Test#broadcasts と #clear_messages が生の引数をキーに使っていたため、保存側と取得側で型が揃わず、assert_broadcasts(:foo, …) が 0 件と判定されたり、assert_no_broadcasts(:foo) が実際にはメッセージが送信されていても 通過 してしまうケースが発生していました。この不整合はテストの信頼性を損ね、潜在的な回帰を隠す危険性がありました。
技術的な変更
actioncable/lib/action_cable/subscription_adapter/test.rb の broadcasts と clear_messages メソッドで、チャネル名を String(channel) に強制変換してからハッシュのキーとして使用するよう修正しました。これにより、シンボル・文字列問わず同一キーでメッセージが格納・参照されます。
@@
- def broadcasts(channel)
- channels_data[channel] ||= []
+ def broadcasts(channel)
+ channels_data[String(channel)] ||= []
end
@@
- def clear_messages(channel)
- channels_data[channel] = []
+ def clear_messages(channel)
+ channels_data[String(channel)] = []
end
さらに、actioncable/test/test_helper_test.rb に test_assert_broadcasts_with_symbol_stream テストを追加し、シンボルストリームでのブロードキャスト検証が正しく成功することを自動確認できるようにしました。
@@
+ def test_assert_broadcasts_with_symbol_stream
+ assert_nothing_raised do
+ assert_broadcasts(:test, 1) do
+ ActionCable.server.broadcast :test, "message"
+ end
+ end
+ end
設計判断
今回の修正は 読み取り側 を 書き込み側 と同一の文字列化ロジックに合わせるというシンプルな選択です。新たなパラメータや API を導入せず、既存のハッシュキー生成ロジックに String(channel) 変換を追加しただけなので、既存のコードベースへの影響は最小限に抑えられます。また、String(channel) は既に broadcast メソッドで使用されているため、型一貫性が保証され、テストアダプターの動作が全体のデータフローと整合します。
まとめ
テストアダプターがシンボルストリーム名を正しく扱えるように変更したことで、assert_no_broadcasts が実際のレグレッションを隠す問題が解消されました。書き込みと読み取りのキー生成を統一したシンプルな設計は、既存コードへのリスクを抑えつつテスト信頼性を向上させます。