我在Michael Hartl的Ruby on Rails 3教程(本书的早期Kindle版本,而不是在线版本)的第9章末尾,并遇到了失败的集成测试(users_spec.rb)。我一直在寻找,但是我找到的建议到目前为止还没有找到。我下载了第一版和第二版教程的源代码,它们运行正常,所以看起来我的应用程序的配置有点不对,但作为一个rails新手,感觉就像在大海捞针一样所以欢迎任何帮助。
错误消息:ActionController :: RoutingError:没有路由匹配[GET]“/ signout”
users_spec.rb包含此
...
describe "success" do
it "should sign a user in and out" do
user = FactoryGirl.create(:user)
visit signin_path
fill_in :email, :with => user.email
fill_in :password, :with => user.password
click_button
controller.should be_signed_in
click_link "Sign out"
controller.should_not be_signed_in
end
end
...
我的application.html.erb看起来像这样
<!DOCTYPE html>
<html>
<head>
<title><%= @title %></title>
<%= javascript_include_tag 'default' %>
<%= csrf_meta_tags %>
<%= render 'layouts/stylesheets' %>
</head>
<body>
<div class='container'>
<%= render 'layouts/header' %>
<section class = "round">
<% flash.each do |key, value| %>
<div class="flash <%= key %>"><%= value %></div>
<% end %>
<%= yield %>
</section>
<%= render 'layouts/footer' %>
<%= debug(params) if Rails.env.development? %>
</div>
</body>
</html>
我的application_controller.rb看起来像这样
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end
我的application.js看起来像这样
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
// GO AFTER THE REQUIRES BELOW.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
_header.html.erb文件包含此
...
<% if signed_in? %>
<li><%= link_to "Sign out", signout_path, :method => :delete %></li>
<% else %>
...
我的routes.rb包含此
...
get "sessions/new"
resources :users
resources :sessions, :only =>[:new, :create, :destroy]
match '/contact', :to => 'pages#contact'
match '/about', :to => 'pages#about'
match '/help', :to => 'pages#help'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
root :to => 'pages#home'
...
我的sessions_controller.rb包含此
...
def destroy
sign_out
redirect_to root_path
end
...
sessions_helper.rb包含此
...
def sign_out
cookies.delete(:remember_token)
@current_user = nil
end
...
这是我执行rake路径时得到的结果
sessions_new GET /sessions/new(.:format) sessions#new
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
sessions POST /sessions(.:format) sessions#create
new_session GET /sessions/new(.:format) sessions#new
session DELETE /sessions/:id(.:format) sessions#destroy
contact /contact(.:format) pages#contact
about /about(.:format) pages#about
help /help(.:format) pages#help
signup /signup(.:format) users#new
signin /signin(.:format) sessions#new
signout DELETE /signout(.:format) sessions#destroy
我的gemfile看起来像这样
source 'https://rubygems.org'
gem 'rails', '3.2.8'
gem 'pg'
gem 'gravatar_image_tag'
gem 'jquery-rails'
group :development do
gem 'rspec-rails'
gem 'annotate'
end
group :test do
gem 'rspec'
gem 'webrat'
gem 'spork'
gem 'factory_girl_rails'
end
运行bundler install时,我将其作为输出:
Using rake (0.9.2.2)
Using i18n (0.6.1)
Using multi_json (1.3.6)
Using activesupport (3.2.8)
Using builder (3.0.4)
Using activemodel (3.2.8)
Using erubis (2.7.0)
Using journey (1.0.4)
Using rack (1.4.1)
Using rack-cache (1.2)
Using rack-test (0.6.2)
Using hike (1.2.1)
Using tilt (1.3.3)
Using sprockets (2.1.3)
Using actionpack (3.2.8)
Using mime-types (1.19)
Using polyglot (0.3.3)
Using treetop (1.4.11)
Using mail (2.4.4)
Using actionmailer (3.2.8)
Using arel (3.0.2)
Using tzinfo (0.3.33)
Using activerecord (3.2.8)
Using activeresource (3.2.8)
Using annotate (2.5.0)
Using diff-lcs (1.1.3)
Using factory_girl (4.1.0)
Using rack-ssl (1.3.2)
Using json (1.7.5)
Using rdoc (3.12)
Using thor (0.16.0)
Using railties (3.2.8)
Using factory_girl_rails (4.1.0)
Using gravatar_image_tag (1.1.3)
Using jquery-rails (2.1.3)
Using nokogiri (1.5.5)
Using pg (0.14.1)
Using bundler (1.2.0)
Using rails (3.2.8)
Using rspec-core (2.11.1)
Using rspec-expectations (2.11.3)
Using rspec-mocks (2.11.3)
Using rspec (2.11.0)
Using rspec-rails (2.11.4)
Using spork (0.9.2)
Using webrat (0.7.3)
可能有趣的是,当通过rails运行我的应用程序时,它也失败了,所以它不仅是一个webrat或失败的集成问题。在查看firbug中的html源代码时,它显示我希望显示的javascript不存在
<script type="text/javascript" src="/assets/jquery.js?body=1">
<script type="text/javascript" src="/assets/jquery_ujs.js?body=1">
点击“退出”时就是结果
答案 0 :(得分:0)
执行摘要
您正在使用webrat而不是capybara,这可以解释为什么我在下面描述的问题出现了。变化:
gem 'webrat'
到
gem 'capybara'
在您的Gemfile中,DELETE请求的javascript点击处理程序应该可以正常工作。
有关所涉问题的更深入讨论,请参阅下面的原始答案。
原始回答
这是一个棘手的问题。在我看来,问题是你的测试没有打开javascript。
一些背景知识:Rails使用名为jquery-ujs的脚本编写适配器来执行各种操作,例如强制确认对话框(当您尝试删除记录时,“是否确定?”消息)并进行非GET来自超链接的请求(因此您可以单击“删除”链接,您的浏览器将发送DELETE请求。)
在您的routes.rb中,您有:
signout DELETE /signout(.:format) sessions#destroy
这就是说:当DELETE请求到达网址/signout
时,请将用户注销。但是,默认情况下,当您单击页面上的链接到URL /signout
时,您的浏览器将发送GET请求,而不是DELETE请求。
当您在此method: destroy
的电话中加入link_to
选项时,
link_to "Sign out", signout_path, :method => :delete
这样做是告诉Rails将属性data-method="delete"
添加到视图中链接的属性上(检查实际呈现的HTML以确定这是真的)。这个属性就像一个标志:它告诉jquery-ujs添加一个点击处理程序,它将这个元素的任何点击从GET变成DELETE。有关详细信息,请参阅this article。另请注意,Hartl在a footnote中提到了这一点。
但是如果在这种情况下没有启用javascript会发生什么?好吧,没有添加最终点击处理程序,并且您的浏览器会像页面上的任何其他链接一样将链接视为/signout
,因此当您单击它时,您会向该URL发送GET请求。但是,Rails没有任何路径可以向/signout
发送GET请求,因此它会发出错误:
ActionController::RoutingError: No route matches [GET] “/signout”
这就是问题的原因。
现在针对该解决方案,我相信您应该能够为您的测试添加一个选项js: true
,这将启用javascript,如下所示:
it "should sign a user in and out", js: true do
...
end
如果您正在使用默认的javascript驱动程序Selenium,这将实际打开一个浏览器窗口 - 运行js测试而不用窗口将capybara-webkit gem添加到您的Gemfile并使用{{设置驱动程序1}}。有关在Rspec请求规范中使用javascript的详细信息,请参阅有关测试javascript的this Railscast部分。
答案 1 :(得分:0)