【问题标题】:how to specify controller and method names in Rspec controller test when using Devise-like route?使用类似设计的路由时,如何在 Rspec 控制器测试中指定控制器和方法名称?
【发布时间】:2015-03-02 07:43:08
【问题描述】:

tl;dr:无法对设计控制器进行 rspec 测试,求助。

我正在使用 Devise 并有以下路线(默认 devise_for 路线):

GET    /users/cancel(.:format)      devise/registrations#cancel
POST   /users(.:format)             devise/registrations#create
GET    /users/sign_up(.:format)     devise/registrations#new
GET    /users/edit(.:format)        devise/registrations#edit
PATCH  /users(.:format)             devise/registrations#update
PUT    /users(.:format)             devise/registrations#update
DELETE /users(.:format)             devise/registrations#destroy

我想使用 Rspec 测试我的控制器方法是否从给定的一组参数中吐出正确的输出。

我的规范文件如下所示:

describe Users::RegistrationsController, type: 'controller' do
  it 'creates a user with given parameters' do

    post 'create', username: 'jonsnow', password: '012345678912345', authenticity_token: '12345'
    expect(response.status).to eq(200)
  end

end

我得到的错误是:

Failure/Error: post 'create', username: 'jonsnow', password: '012345678912345', authenticity_token: '12345'
ActionController::UrlGenerationError: 
No route matches {:action=>"create", :controller=>"users/registrations"}

这是有道理的,因为我使用的是devise_for 默认路由,从rake routes 结果中可以看出,正确的路由是devise/registrations#create,但我似乎找不到指定控制器名称的方法到devise/registrations。我认为它是从控制器类名或users/registrations 中“变形”的。而且我最好避免弄乱我的路线,以使我的测试成功。我怎样才能做到这一点? (请解释)提前致谢。

我的 gem 版本:

rspec '3.2.1'
ruby '2.1.5'
rails '4.2.0'

【问题讨论】:

  • 不确定Users::RegistrationsController 是否正确?也许Devise
  • 这是 Devise::RegistrationsController 子类的名称。如果我正在测试我的控制器子类,它不应该以它命名吗?否则我将无法测试我的控制器方法。
  • 大多数人会争辩说您不会对此进行测试,因为在设计 gem 中已经进行了数千次测试以确保其有效。 github.com/plataformatec/devise/tree/master/test/controllers
  • 您将进行集成测试,以确保您可以使用 capybara 之类的工具实际登录
  • @Anthony 这根本没有帮助。我在网上阅读的所有内容要么不完整,要么让我远离这个简单的动作。您指出可能没有必要对其进行测试,但我不明白开发人员如何坚持独立于路由表测试控制器,但是在测试控制器响应时,这就是控制器在首先,它们迫使您返回路线,但无法明确说明哪个控制器和动作,一切似乎都是推断出来的。是我还是那只是糟糕的设计?

标签: ruby-on-rails ruby rspec devise


【解决方案1】:

需要一些额外的配置才能测试从 Devise 继承的控制器。

describe YourControllerWhichInheritsDevise, type: 'controller' do
  before do
    @request.env["devise.mapping"] = Devise.mappings[:user]
  end

  it 'creates a user with given parameters' do
    post 'create', username: 'jonsnow', password: '012345678912345', authenticity_token: '12345'
    expect(response.status).to eq(200)
  end
end

From the Devise README: “如果您正在测试 Devise 内部控制器或从 Devise 继承的控制器,您需要在请求之前告诉 Devise 应该使用哪个映射。这是必要的,因为 Devise 从路由器获取此信息,但由于功能测试不会通过路由器,需要明确说明。”

【讨论】:

  • 我认为这里的文档具有误导性,但这意味着如果您使用的是设计模型,则应该添加设计映射语句。我得出这个结论是因为我在我的场景中测试了那行代码,但它没有帮助。
  • 请不要删除这个帖子,它是为社区服务的:)
  • 那么我相信您还有另一个问题,可能与您如何为控制器命名空间有关。我已经做了很多次你想做的事情;我打赌你会找到我上面的解决方案,虽然它可能无法解决你目前遇到的任何问题,但仍然是必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 2017-10-04
  • 1970-01-01
相关资源
最近更新 更多