在Rails Controller测试中,有没有办法传递查询(非路由)参数?

时间:2012-12-13 18:39:58

标签: ruby-on-rails ruby testing rspec

我正在Rails和RSpec中编写控制器测试,从阅读ActionController::TestCase的源代码看,它不可能将任意查询参数传递给控制器​​ - 只有路由参数。

要解决此限制,我目前正在使用with_routing

with_routing do |routes|
  # this nonsense is necessary because
  # Rails controller testing does not
  # pass on query params, only routing params

  routes.draw do 
    get '/users/confirmation/:confirmation_token' => 'user_confirmations#show'
    root :to => 'root#index'
  end

  get :show, 'confirmation_token' => CONFIRMATION_TOKEN
end

正如您可能猜到的那样,我正在测试Devise的自定义Confirmations控制器。这意味着我正在使用现有的API,并且无法更改config/routes.rb中实际映射的完成方式。

有更简洁的方法吗? get支持的方式传递查询参数?


编辑: 正在进行其他事情。我在https://github.com/clacke/so_13866283中创建了一个最小的例子:

spec/controllers/receive_query_param_controller_spec.rb

describe ReceiveQueryParamController do
  describe '#please' do
    it 'receives query param, sets @my_param' do
      get :please, :my_param => 'test_value'
      assigns(:my_param).should eq 'test_value'
    end
  end  
end

app/controllers/receive_query_param_controller.rb

class ReceiveQueryParamController < ApplicationController
  def please
    @my_param = params[:my_param]
  end
end

config/routes.rb

So13866283::Application.routes.draw do
  get '/receive_query_param/please' => 'receive_query_param#please'
end

这个测试通过了,所以我认为它是Devise,可以通过路由做一些时髦的事情。


编辑:

确定定义Devise路线的位置,并更新我的示例应用以匹配它。

So13866283::Application.routes.draw do
  resource :receive_query_param, :only => [:show],
    :controller => "receive_query_param"
end

...并且相应地更新规范和控制器以使用#show。测试仍然通过,即params[:my_param]填充get :show, :my_param => 'blah'。所以,仍然有一个谜,为什么这不会发生在我的真实应用程序中。

3 个答案:

答案 0 :(得分:3)

控制器测试不会路由。您正在对控制器进行单元测试 - 路由超出了其范围。

典型的控制器规范示例测试操作:

describe MyController do
  it "is successful" do
    get :index
    response.status.should == 200
  end
end

您可以通过将参数传递给get来设置测试上下文,例如:

  get :show, :id => 1

您可以在该哈希中传递查询参数。

如果您 想要测试路由,您可以编写路由规范或请求(集成)规范。

答案 1 :(得分:1)

你确定没有其他事情发生吗?我有一个Rails 3.0.x项目,并且正在传递参数..好吧..这是一个帖子..也许它与get有所不同,但这看起来很奇怪..

before  { post :contact_us, :contact_us => {:email => 'joe@example.com',
         :category => 'Category', :subject => 'Subject', :message => 'Message'} }

以上内容肯定在params对象的控制器中使用。

答案 2 :(得分:1)

我现在正在这样做:

@request.env['QUERY_STRING'] = "confirmation_token=" # otherwise it's ignored
get :show, :confirmation_token => CONFIRMATION_TOKEN

......但它看起来很黑。

如果有人能给我一个干净利落的官方方式,我会很高兴。从我在#get的源代码中看到的内容以及它所调用的一切来看,似乎没有其他任何方式,但我希望我忽略了一些东西。