在Rails 4控制器中使用时,处理问题测试的最佳方法是什么?假设我有一个小问题.

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

测试中的预期行为是,任何包含此问题的控制器都会得到这citations个端点.

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.

推荐答案

在你的"范围"中包含了许多控制器示例,告诉你如何使用它们.

我个人认为这比杀戮更重要,更喜欢单独执行单元测试,然后使用集成测试来确认控制器的行为.

Method 1: without routing or response testing

创建一个假控制器并测试其方法:

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

Method 2: testing response

当您的问题包含路由或需要测试响应、渲染等时...您需要使用匿名控制器运行测试.这允许您访问所有与控制器相关的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)定义匿名控制器.如果你的考试涉及ApplicationController以外的其他课程,你需要调整这个.

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

config.infer_base_class_for_anonymous_controllers = true

Note: keep testing that your concern is included

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

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

Ruby-on-rails相关问答推荐

参数数量错误(给定1个,预期为0个;必需关键字:IO、文件名)-活动存储

Rails + Turbo_stream自定义操作:我可以在没有Stimulus的情况下根据DOM状态做出有条件的响应吗?

Rails:比枚举更惯用的排序/可比较列表方法?

Rails 使用多个外键创建/构建

Rails 7 - has_many_attached 在加载新附件时删除旧附件

为什么总是有东西在我的 mac 上的 5000 端口运行

为 ActionMailer 渲染不同的视图(模板)

在 Rails 中找不到关联问题

Ruby on Rails 取消首字母大写

使用 RVM 时如何安装 Ruby gem?

SQLite3::BusyException

在 Nokogiri 中获取属性值以提取链接 URL

Rails:使用 RSpec 测试命名范围

默认情况下,如何在 Rails 中使 cookie 安全(仅限 https)?

Rails - 生产模式下的错误

如何在 Rails 应用程序中使用长 id?

rails 4 before_validation on: :create 或 on: :save

rake 任务中的 def 块

何时在 Ruby on Rails 中使用 lambda?

如何在不触及 updated_at 属性的情况下更新单个属性?