ruby-on-rails - 如何在 Rails 4 中测试 Controller 问题

标签 ruby-on-rails rspec controller activesupport-concern

在 Rails 4 Controller 中使用时处理关注点测试的最佳方法是什么?假设我有一个微不足道的问题Citations

module Citations
    extend ActiveSupport::Concern
    def citations ; end
end

测试中的预期行为是任何包含此问题的 Controller 都会获得此引用端点。

class ConversationController < ActionController::Base
    include Citations
end

简单。

ConversationController.new.respond_to? :yelling #=> true

但是单独测试这个问题的正确方法是什么?

class CitationConcernController < ActionController::Base
    include Citations
end

describe CitationConcernController, type: :controller do
    it 'should add the citations endpoint' do
        get :citations
        expect(response).to be_successful
    end
end

不幸的是,这失败了。

CitationConcernController
  should add the citations endpoint (FAILED - 1)

Failures:

  1) CitationConcernController should add the citations endpoint
     Failure/Error: get :citations
     ActionController::UrlGenerationError:
       No route matches {:controller=>"citation_concern", :action=>"citations"}
     # ./controller_concern_spec.rb:14:in `block (2 levels) in <top (required)>'

这是一个人为的例子。在我的应用程序中,我收到了不同的错误。

RuntimeError:
  @routes is nil: make sure you set it in your test's setup method.

最佳答案

您会发现许多建议告诉您使用共享示例并在包含的 Controller 范围内运行它们。

我个人认为它太过分了,更喜欢单独执行单元测试,然后使用集成测试来确认我的 Controller 的行为。

方法 1:无需路由或响应测试

创建一个假 Controller 并测试其方法:

describe MyControllerConcern do
  before do
    class FakesController < ApplicationController
      include MyControllerConcern
    end
  end

  after do
    Object.send :remove_const, :FakesController 
  end

  let(:object) { FakesController.new }

  it 'my_method_to_test' do
    expect(object).to eq('expected result')
  end

end

方法2:测试响应

当您关注的是路由或者您需要测试响应、渲染等时...您需要使用匿名 Controller 运行测试。这允许您访问所有与 Controller 相关的 rspec 方法和帮助器:

describe MyControllerConcern, type: :controller do
  controller(ApplicationController) do
    include MyControllerConcern

    def fake_action; redirect_to '/an_url'; end
  end

  before do
    routes.draw {
      get 'fake_action' => 'anonymous#fake_action'
    }
  end
    
  describe 'my_method_to_test' do
    before do
      get :fake_action 
    end

    it do
      expect(response).to redirect_to('/an_url') 
    end
  end
end

如您所见,我们使用 controller(ApplicationController) 定义匿名 Controller 。如果您的测试涉及 ApplicationController 之外的其他类,您将需要对此进行调整。

此外,为了使其正常工作,您必须在 spec_helper.rb 文件中配置以下内容:

config.infer_base_class_for_anonymous_controllers = true

注意:不断测试您的问题是否包含在内

测试您的关注类是否包含在目标类中也很重要,一行就足够了:

describe SomeTargetedController do
  it 'includes MyControllerConcern' do
    expect(SomeTargetedController.ancestors.include? MyControllerConcern).to be(true) 
  end
end

关于ruby-on-rails - 如何在 Rails 4 中测试 Controller 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22055889/

相关文章:

javascript - 如何将 ngChange 保存在本地存储中

java - spring mvc-在调用 Controller 函数之前调用函数

ruby-on-rails - 如何初始化 Rack 服务器监听套接字

ruby-on-rails - "WARNING: Can' t 验证 CSRF token 真实性”错误 - 带有设计和 :token_authenticatable 的 CORS

rspec - 除非期望的文件位于某个目录中,否则包含模块?

ruby - RSpec:如何监视与现有对象的交互?

c# - 如何将联接表传递给 MVC 中的 View ?

ruby-on-rails - Rails 与 group by 和 include 求和

ruby-on-rails - 对 Rails 应用程序 Controller 的辅助模块进行单元测试 - 如何进行?

ruby-on-rails - 使用 Rspec 的 Rails 5 邮件程序预览