Madogiwa Blog

主に技術系の学習メモに使っていきます。

Ruby on Rails: テスト用にrouteを動的に追加するメモ📝

テスト用にRoutingを動的にいじってテストしたいことがたまにあるのでやり方をメモ📝

まず以下のようなテスト用のhelperを用意します。 中でやっていることは動的にrouteを追加するdraw_test_routesとそれをリセットするreload_routes!を実装しています。

module RoutesHelper
  def draw_test_routes(&block)
    Rails.application.routes.disable_clear_and_finalize = true

    Rails.application.routes.draw do
      instance_exec(&block)
    end
  end

  def reload_routes!
    Rails.application.reload_routes!
  end
end

Rails.application.routes.disable_clear_and_finalize = trueをすることで以下のroutesのclearやfinalizeを無効化してroutesを固定化させず、動的に追加したものを初期化させないようにします。

https://github.com/rails/rails/blob/v7.1.2/actionpack/lib/action_dispatch/routing/route_set.rb#L428-L433

またRails.application.reload_routes!を実行することで、clear!し再読み込みされfinalize!することで動的に追加したroutesを削除するとともにRails.application.routes.disable_clear_and_finalizeがfalseに再設定されるので、元に戻ります。

https://github.com/rails/rails/blob/v7.1.2/railties/lib/rails/application/routes_reloader.rb#L22-L29

以下の通り、任意のcontrollerを使って動的にrouteを追加することができました🎉

require "spec_helper"
require_relative "../../test/support/routes_helper"

class TestsController < ActionController::Base
  def index
    head :ok
  end
end

describe "GET /test", type: :request do
  include RoutesHelper

  before(:example) do
    draw_test_routes do
      get "/tests", to: "tests#index"
    end
  end

  after(:example) do
    reload_routes!
  end

  it "success" do
    get "/tests"
    expect(response).to have_http_status :ok
  end
end

参考

techracho.bpsinc.jp