2013-11-25 88 views
2

我只有一个规格,位于spec/controllers/statuses_spec.rb我应该如何测试rspec的路由和控制器?

下面是它的内容:

require 'spec_helper' 

describe StatusesController do 
    describe "routing" do 

    it "routes to #index" do 
     get("/statuses").should route_to("statuses#index") 
    end 

    end 
end 

我只想说,我有一个简单的状态脚手架和状态控制器具有CRUD的标准动作,包括索引行动。

然而,运行上述测试时,我得到这个故障:

15:39:52 - INFO - Running: ./spec/controllers/statuses_spec.rb:6 
Run options: include {:locations=>{"./spec/controllers/statuses_spec.rb"=>[6]}} 
F 

Failures: 

    1) StatusesController routing routes to #index 
    Failure/Error: get("/statuses").should route_to("statuses#index") 
    ActionController::UrlGenerationError: 
     No route matches {:controller=>"statuses", :action=>"/statuses"} 
    # ./spec/controllers/statuses_spec.rb:8:in `block (3 levels) in <top (required)>' 

Finished in 0.21772 seconds 
1 example, 1 failure 

Rspec的让我正在着手处理与statuses控制器,它是那种直觉我猜是因为我在引用它的假设我spec的描述块,它认为我传入get方法的字符串('/ statuses')是函数。

坦率地说,我不太喜欢这个。我希望能够测试URL栏中的确切字符串是否正确到控制器#操作对。无论如何,我一样rspec的说和做:

require 'spec_helper' 

describe StatusesController do 
    describe "routing" do 

    it "routes to #index" do 
     get("index").should route_to("statuses#index") 
    end 

    end 
end 

不过,现在我得到这样的:

Run options: include {:locations=>{"./spec/controllers/statuses_spec.rb"=>[6]}} 
F 

Failures: 

    1) StatusesController routing routes to #index 
    Failure/Error: get("index").should route_to("statuses#index") 
    NoMethodError: 
     undefined method `values' for #<ActionController::TestResponse:0x00000102bd3208> 
    # ./spec/controllers/statuses_spec.rb:8:in `block (3 levels) in <top (required)>' 

Finished in 0.31019 seconds 
1 example, 1 failure 

Failed examples: 

rspec ./spec/controllers/statuses_spec.rb:6 # StatusesController routing routes to #index 

我收到有关一个values方法没有方法错误。值?严重的是,什么?我不知道为什么我得到这个错误。这里是我的帮手:

# This file is copied to spec/ when you run 'rails generate rspec:install' 
ENV["RAILS_ENV"] ||= 'test' 
require File.expand_path("../../config/environment", __FILE__) 
require 'rspec/rails' 
require 'rspec/autorun' 
require 'capybara/rspec' 

# Requires supporting ruby files with custom matchers and macros, etc, 
# in spec/support/ and its subdirectories. 
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } 

# Checks for pending migrations before tests are run. 
# If you are not using ActiveRecord, you can remove this line. 
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration) 

RSpec.configure do |config| 
    # ## Mock Framework 
    # 
    # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: 
    # 
    # config.mock_with :mocha 
    # config.mock_with :flexmock 
    # config.mock_with :rr 
    config.before(:suite) do 
    DatabaseCleaner.strategy = :transaction 
    DatabaseCleaner.clean_with(:truncation) 
    end 

    config.before(:each) do 
    Capybara.run_server = true 
    Capybara.javascript_driver = :webkit 
    Capybara.default_selector = :css 
    Capybara.server_port = 7171 
    DatabaseCleaner.start 
    end 

    config.after(:each) do 
    DatabaseCleaner.clean 
    end 

    # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures 
    config.fixture_path = "#{::Rails.root}/spec/fixtures" 

    config.include RSpec::Rails::RequestExampleGroup, type: :feature 

    # If you're not using ActiveRecord, or you'd prefer not to run each of your 
    # examples within a transaction, remove the following line or assign false 
    # instead of true. 
    config.use_transactional_fixtures = true 

    # If true, the base class of anonymous controllers will be inferred 
    # automatically. This will be the default behavior in future versions of 
    # rspec-rails. 
    config.infer_base_class_for_anonymous_controllers = false 

    # Run specs in random order to surface order dependencies. If you find an 
    # order dependency and want to debug it, you can fix the order by providing 
    # the seed, which is printed after each run. 
    #  --seed 1234 
    config.order = "random" 
end 
+0

路由规格不属于/控制器文件夹 – apneadiving

+0

啊有道理 – Starkers

+1

阅读文档:https://www.relishapp.com/rspec/rspec-rails/v/3-0/docs/routing-specs – apneadiving

回答

5

测试路由,特别是标准的RESTful路由,并不是标准的做法。

一)你不想浪费精力重新测试Rails的路由功能

B)您的控制器或request规格发生故障时也不能请求路由

更多的时候不是,编写和维护路由测试没有提供太多的价值和增强的信心。 当路由变得复杂且容易出错时,请考虑测试路由。

也就是说,RSpec提供了一个route_to matcher用于指定请求是可路由的。

路由规范的推荐位置在spec/routing之下,不过在路由规格旁边看到路由规格并不罕见。例如

describe VersionsController do 
    describe 'routing' do 
    it 'routes GET /version to VersionsController#show' do 
     expect(get: '/version').to route_to(controller: 'versions', action: 'show') 
    end 
    end 
end 

shoulda-matchers gem有自己的路线匹配,允许你编写的测试,如

describe PostsController do 
    it { should route(:get, '/posts').to(action: :index) } 
    it { should route(:get, '/posts/1').to(action: :show, id: 1) } 
end 
+0

大声笑得爱完成重写1.5年后;) – jtmarmon

+0

@jtmarmon早期downvotes是当之无愧的,是时候重写:) – Dennis

+0

谢谢。我认为路由规范通常是不需要的,但是当我们对约束对象和什么都不熟悉时,将它们用作单元测试是正确的。 –

1

路线应作为集成测试的一部分。集成测试是测试应用程序重要工作流程的地方 - 更具体地说,是否定义了URL是否是一个重要的工作流程。

你的集成测试看起来像任何正常的集成测试:

require 'test_helper' 
class RoutesTest < ActionController::IntegrationTest 
    test "route test" do 
     assert_generates "/videos/5", { :controller => "videos", :action => "show", :id => "1" } 
     assert_generates "/about", :controller => "pages", :action => "about" 
    end 
end 

至于@ jemminger的不是测试路线的回应 - 尽管它是一个验证的routes.rb作品铁路的测试,这不是轨道的责任测试http://yoursite.com/users是否在您的路线中定义。需要注意的是,大多数路由测试可以在现有的集成测试中完成,因此路由的特定测试可能是多余的。

我能想到的具体用例是所有已经或将要从Rails 2升级到Rails 3的用户。定义路由的代码已经发生了显着变化,最好从测试中找出路由已正确升级,而用户在报告404错误时正确升级。

相关问题