如何在Rails 4中测试控制器问题 [英] How to test a Controller Concern in Rails 4

查看:76
本文介绍了如何在Rails 4中测试控制器问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Rails 4控制器中使用时,处理关注点测试的最佳方法是什么?说我有个琐碎的问题 Citations

What is the best way to handle testing of concerns when used in Rails 4 controllers? Say I have a trivial concern Citations.

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

在测试中的预期行为是,任何包含此担忧的控制器都将得到这个 citations 端点。

The expected behavior under test is that any controller which includes this concern would get this citations endpoint.

class ConversationController < ActionController::Base
    include Citations
end

简单。

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

但是孤立地测试此问题的正确方法是什么?

But what is the right way to test this concern in isolation?

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)>'

这是一个人为的示例。在我的应用中,我收到另一个错误。

This is a contrived example. In my app, I get a different error.

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


推荐答案

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

You will find many advice telling you to use shared examples and run them in the scope of your included controllers.

我个人认为它过分杀了,宁愿单独执行单元测试,然后使用集成测试来确认控制器的行为。

I personally find it over-killing and prefer to perform unit testing in isolation then use integration testing to confirm the behavior of my controllers.

方法1:不进行路由或响应测试

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

Create a fake controller and test its methods:

describe MyControllerConcern do

  before do
    class FakesController < ApplicationController
      include MyControllerConcern
    end
  end
  after { Object.send :remove_const, :FakesController }
  let(:object) { FakesController.new }

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

end

方法2:测试响应

何时您的关注点包含路由,或者您需要测试响应,渲染等...您需要使用匿名控制器运行测试。这使您可以访问所有与控制器相关的rspec方法和帮助器:

When your concern contains routing or you need to test for response, rendering etc... you need to run your test with anonymous controller. This allow you to gain access to all controller-related rspec methods and helpers:

describe MyControllerConcern, type: :controller do

  controller(ApplicationController) do
    include MyControllerConcern

    def fake_action; redirect_to '/an_url'; end
  end
  before { routes.draw {
    get 'fake_action' => 'anonymous#fake_action'
  } }


  describe 'my_method_to_test' do
    before { get :fake_action }
    it { expect(response).to redirect_to('/an_url') }
  end
end

您可以看到我们必须将匿名控制器包装在 controller(ApplicationController)中。如果您的类是从 ApplicationController 以外的其他类继承的,则需要对此进行调整。

You can see that we have to wrap the anonymous controller in a controller(ApplicationController). If your classes are inherited from another class than ApplicationController, you will need to adapt this.

工作正常,您必须在您的 spec_helper.rb 文件中声明:

Also for this to work properly you must declare in your spec_helper.rb file:

config.infer_base_class_for_anonymous_controllers = true

注意:请继续测试是否已包含您的担忧

测试一下关注类别是否包含在目标类别中也很重要,只需一行即可:

It is also important to test that your concern class is included in your target classes, one line suffice:

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

这篇关于如何在Rails 4中测试控制器问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆