RubricksにおけるURIの問題(2)

前回の修正によって、アプリケーションの動作的には問題が解決されたが、Functionalテストが全て通らなくなるという問題が発生した。エラー内容は前回と同様に「url_forでURLが生成できません」ということだった。


テストの処理ではApplicationControllerの設定をみてくれないのだろうということで、テスト用のmockでpostメソッドやgetメソッドにおけるparameterに直接メインのデフォルト値をねじこもうと試みる。これが中々上手くいかずに苦戦した。というのも、「def post」や「def get」で検索をかけてヒットしたファイルの周辺を解析していったんだけど、どうもテストでは使ってないみたい。

結局、以下の部分が該当すると判明した。文字列を変数展開してメソッドを宣言するとか、ものすごい豪快だね。。。そりゃ引っかからないわけだ。

[/actionpack-1.X.X/lib/action_controller/test_process.rb]
  module TestProcess
    def self.included(base)
      # execute the request simulating a specific http method and set/volley the response
      %w( get post put delete head ).each do |method|
        base.class_eval <<-EOV, __FILE__, __LINE__
          def #{method}(action, parameters = nil, session = nil, flash = nil)
            @request.env['REQUEST_METHOD'] = "#{method.upcase}" if @request
            process(action, parameters, session, flash)
          end
        EOV
      end
    end

    # execute the request and set/volley the response
    def process(action, parameters = nil, session = nil, flash = nil)
      # Sanity check for required instance variables so we can give an
      # understandable error message.
      %w(controller request response).each do |iv_name|
        raise "@#{iv_name} is nil: make sure you set it in your test's setup method." if instance_variable_get("@#{iv_name}").nil?
      end

      @request.recycle!

      @html_document = nil
      @request.env['REQUEST_METHOD'] ||= "GET"
      @request.action = action.to_s

      parameters ||= {}
      @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)

      @request.session = ActionController::TestSession.new(session) unless session.nil?
      @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
      build_request_uri(action, parameters)
      @controller.process(@request, @response)
    end

というわけで以下のようなmockを作って対処。こっちも十分豪快か。

ActionController::TestProcess.class_eval do
  def process_with_main(action, parameters = nil, session = nil, flash = nil)
    # Sanity check for required instance variables so we can give an
    # understandable error message.
    %w(controller request response).each do |iv_name|
      raise "@#{iv_name} is nil: make sure you set it in your test's setup method." if instance_variable_get("@#{iv_name}").nil?
    end

    @request.recycle!

    @html_document = nil
    @request.env['REQUEST_METHOD'] ||= "GET"
    @request.action = action.to_s

    parameters ||= {}
    parameters.reverse_merge!(:main => 'main')
    @request.assign_parameters(@controller.class.controller_path, action.to_s, parameters)

    @request.session = ActionController::TestSession.new(session) unless session.nil?
    @request.session["flash"] = ActionController::Flash::FlashHash.new.update(flash) if flash
    build_request_uri(action, parameters)
    @controller.process(@request, @response)
  end
  alias_method :process, :process_with_main
end