4

我在 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 对路由做了一些时髦的事情。


编辑:

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

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'。因此,为什么在我的真实应用程序中不会发生这种情况仍然是个谜。

4

3 回答 3

3

控制器测试不路由。您正在对控制器进行单元测试——路由超出了它的范围。

一个典型的控制器规范示例测试一个动作:

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

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

  get :show, :id => 1

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

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

于 2012-12-14T00:47:10.213 回答
1

你确定没有其他事情发生吗?我有一个 Rails 3.0.x 项目并且正在传递参数.. 嗯.. 这是一篇文章.. 也许它与 get 不同,但这似乎很奇怪..

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

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

于 2012-12-13T21:12:19.087 回答
1

我现在正在这样做:

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

...但它看起来很老套。

如果有人可以向我展示一种简洁而正式的方式来做到这一点,我会很高兴。从我在源代码中看到的#get以及它调用的所有内容来看,似乎没有任何其他方式,但我希望我忽略了一些东西。

于 2012-12-14T20:52:20.260 回答