我只有一个规范,位于spec/controllers/statuses_spec.rb
以下是其内容:
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
控制器,我觉得这很直观,因为我在规范的描述块中引用了它,它认为我已经传入了get的字符串method('/ statuses')就是函数。
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 :(得分:8)
测试路线,尤其是标准的RESTful路线,不是标准做法。
a)你不想浪费时间重新测试Rails&#39;路由功能
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
答案 1 :(得分:1)
Routes should be done as part of integration tests. Integration tests are where you test the important work flows of your application - more specifically whether a URL is defined or not seems to be an important workflow.
Your integration test would look like any normal integration test:
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
As to @jemminger's response of not testing routes - While it is Rail's tests that verify that routes.rb works, it's not Rail's responsibility to test whether http://yoursite.com/users is defined in your routes. The caveat is that most route testing could be done in existing integration tests, so specific tests for routes could be redundant.
The specific use case I can think of are all the people that have already, or are going to upgrade from Rails 2 to Rails 3. The code to define routes has changed significantly, and it's better to find out from tests that the routes were upgraded correctly, than from users when they report 404 errors.
答案 2 :(得分:0)
it { expect(put: "/posts/1").to route_to(controller: "posts", action: "update", id: "1") }
it { expect(GET: "/posts/1").to route_to(controller: 'posts', action: 'show', id: "1") }
if { expect(get: '/posts').to route_to(controller: 'posts', action: 'index') }
如果没有删除路径
it { expect(delete: "/posts/1").to_not be_routable }