minitest 6.x の `assert_nil` 変更に対応した Mime::NullType テストの修正
minitest の assert_nil がオブジェクトの nil? メソッドではなく nil == obj による同値比較に変更されたことで、Mime::NullType を返すケースのテストが失敗するようになりました。本PRはその非互換を解消するテスト修正です。
背景
Railsでは、未知のフォーマットが要求された際に request.format が Mime::NullType のインスタンスを返します。Mime::NullType は nil? が true を返す「null オブジェクトパターン」の実装であり、nil そのものではありません。同様に、ActionText の message.content も内容が存在しない場合に nil? が true を返す null オブジェクトを返します。
これらのオブジェクトは minitest/minitest@c471347 による assert_nil の実装変更によって問題が顕在化しました。従来の assert_nil は obj.nil? を呼び出して真偽を判定していましたが、変更後は nil == obj という同値比較に切り替わっています。Mime::NullType のインスタンスは nil と同値ではないため、assert_nil がこれらのオブジェクトに対して失敗するようになりました。
Gemfile.lock の差分が示すように、本PRは minitest を 6.0.0 から 6.0.6 へ更新しており、この変更を取り込んだバージョンでテストが通ることを確認しています。
技術的な変更
assert_nil を assert_equal true, obj.nil? に置き換えることで、null オブジェクトの nil? メソッドを明示的に検証するよう修正されています。変更対象は以下の3箇所です:
actionpack/test/dispatch/request_test.rb での変更:
変更前:
assert_nil request.format
変更後:
assert_equal true, request.format.nil?
actiontext/test/unit/model_test.rb での変更(2箇所):
変更前:
assert_nil message.content
変更後:
assert_equal true, message.content.nil?
いずれも assert_nil の後に続く assert_not_predicate による html?・xml?・json?・blank?・empty? の検証はそのまま維持されています。
設計判断
assert_nil の暗黙的な振る舞いに依存せず、オブジェクトが持つ nil? メソッドの戻り値を直接検証する形 に変更されています。
assert_nil は「対象が nil である」という検証として広く使われますが、null オブジェクトパターンでは「nil そのものではないが nil? は true を返す」という契約が成立します。assert_equal true, obj.nil? という形式は、この契約——すなわち nil との同値性ではなく nil? メソッドの振る舞い——をテストが明示的に表現していることを示します。
本変更はテストコードのみへの修正であり、本体のロジックには一切手を加えていません。Mime::NullType の振る舞い自体は変更されておらず、テストがその契約を正確に記述するように更新されたといえます。
まとめ
本PRは、minitest の assert_nil 実装変更によって露わになった「null オブジェクトは nil ではない」というセマンティクスの齟齬をテスト側で明示的に修正した変更です。nil? メソッドによる明示的な検証への切り替えにより、null オブジェクトパターンの契約がテストコードに正確に反映されるようになりました。