7

我收到以下错误,不知道如何修复它。Stack Overflow 上还有一些其他页面解决了类似的问题,但这些似乎并不适用,或者至少我不够精明,无法解决。

当我运行 authentication_pages_spec 时,问题似乎与使用“补丁”有关,导致以下失败。请注意,我已经尝试用“put”替换“patch”并得到相同的结果。

Failures:

1) Authentication authorization for non-signed-in users in the Users controller submitting to the update action 
 Failure/Error: before { patch user_path(user) }
 NoMethodError:
   undefined method `patch' for #<RSpec::Core::ExampleGroup::Nested_1::Nested_3::Nested_1::Nested_1::Nested_2:0x007fa7e4df1e50>
 # ./spec/features/authentication_pages_spec.rb:59:in `block (6 levels) in <top (required)>'

Finished in 0.34392 seconds
2 examples, 1 failure

注意:根据此处关于Stack Overflow 的讨论以及此处引用的博客,我选择将我的 spec/requests 文件夹更改为 spec/features,因为这似乎是 Capybara 在 2.0 版之后所需要的。

这是我的 Gemfile:source ' https://rubygems.org ' ruby​​ '2.0.0' #ruby-gemset=railstutorial_rails_4_0

gem 'rails', '4.0.0'
gem 'bootstrap-sass', '2.3.2.0'
gem 'pg', '0.15.1'
gem 'bcrypt-ruby', '3.0.1'

group :development, :test do
  gem 'rspec-rails', '2.13.1'
  gem 'guard-rspec', '2.5.0'
  gem 'spork-rails', github: 'sporkrb/spork-rails'
  gem 'guard-spork', '1.5.0'
  gem 'childprocess', '0.3.9'
end

group :test do
  gem 'selenium-webdriver', '2.0.0'
  gem 'capybara', '2.1.0'
  gem 'growl', '1.0.3'
  gem 'factory_girl_rails', '4.2.1'
  gem 'cucumber-rails', '1.3.0', :require => false
  gem 'database_cleaner', github: 'bmabey/database_cleaner'
end

gem 'sass-rails', '4.0.0'
gem 'uglifier', '2.1.1'
gem 'coffee-rails', '4.0.0'
gem 'jquery-rails', '2.2.1'
gem 'turbolinks', '1.1.1'
gem 'jbuilder', '1.0.2'

group :doc do
  gem 'sdoc', '0.3.20', require: false
end

group :production do
  gem 'pg', '0.15.1'
  gem 'rails_12factor', '0.0.2'
end

我修改了我的 Guardfile 以使用 spec/features 文件夹而不是 spec/requests 文件夹:

    require 'active_support/inflector'

guard 'spork',  :cucumber_env => { 'RAILS_ENV' => 'test' },
                :rspec_env    => { 'RAILS_ENV' => 'test' } do

  watch('config/application.rb')
  watch('config/environment.rb')
  watch('config/environments/test.rb')
  watch(%r{^config/initializers/.+\.rb$})
  watch('Gemfile')
  watch('Gemfile.lock')
  watch('spec/spec_helper.rb') { :rspec }
  watch('test/test_helper.rb') { :test_unit }
  watch(%r{features/support/}) { :cucumber }
end

guard 'rspec', all_after_pass: false, cli: '--drb' do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails example
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^app/(.*)(\.erb|\.haml)$})                 { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }

  # Capybara features specs
  watch(%r{^app/views/(.+)/.*\.(erb|haml)$})          { |m| "spec/features/#{m[1]}_spec.rb" }

  # Turnip features and steps
  watch(%r{^spec/acceptance/(.+)\.feature$})
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }

  # Custom Rails Tutorial specs
  watch(%r{^app/controllers/(.+)_(controller)\.rb$}) do |m|
    ["spec/routing/#{m[1]}_routing_spec.rb",
    "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb",
    "spec/acceptance/#{m[1]}_spec.rb",
    (m[1][/_pages/] ? "spec/features/#{m[1]}_spec.rb" :
                      "spec/features/#{m[1].singularize}_pages_spec.rb")]
  end
  watch(%r{^app/controllers/sessions_controller\.rb$}) do |m|
    "spec/features/authentication_pages_spec.rb"
  end
end

用户控制器在这里:

class UsersController < ApplicationController
    attr_accessor :name, :email
  before_action :signed_in_user, only: [:edit, :update]

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      sign_in @user
        flash[:success] = "Welcome to the Sample App!"
        redirect_to @user
    else
        flash[:error] = "Oops!"
        render 'new'
    end
  end

  def edit
    @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update_attributes(user_params)
      flash[:success] = "Profile updated"
      sign_in @user
      redirect_to @user
    else
      render 'edit'
    end
  end

  private

    def user_params
        params.require(:user).permit(:name, 
                        :email, :password, :password_confirmation)
    end

    # Before filters

    def signed_in_user
      redirect_to signin_url, notice: "Please sign in." unless signed_in?
    end
end

规范帮助文件在这里:

require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'


Spork.prefork do
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'

  Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
  ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)

  RSpec.configure do |config|

    config.fixture_path = "#{::Rails.root}/spec/fixtures"

    config.use_transactional_fixtures = true

    config.infer_base_class_for_anonymous_controllers = false

    config.order = "random"

    config.include Capybara::DSL

    # Added below myself, troubleshooting an 'undefined method 'patch'' message
    config.include Rails.application.routes.url_helpers   
  end
end

Spork.each_run do
  # This code will be run each time you run your specs.

end

最后,为了更好地衡量,config/routes.rb 文件在这里:

SampleApp::Application.routes.draw do
  resources :users
  resources :sessions, only: [:new, :create, :destroy]

  root 'static_pages#home'

  match '/signup',    to: 'users#new',             via: 'get'
  match '/signin',    to: 'sessions#new',          via: 'get'
  match '/signout',   to: 'sessions#destroy',      via: 'delete'
  match '/help',      to: 'static_pages#help',     via: 'get'
  match '/about',     to: 'static_pages#about',    via: 'get'
  match '/contact',   to: 'static_pages#contact',  via: 'get'

这里有关于 Stack Overflow 的类似讨论,但该帖子的答案是将测试从 ./spec/requests 移动到 ./spec/features - 我已经完成了。

此处的另一个相关讨论,答案是require 'spec_helper'在功能文件的顶部使用......我已经有了。

最后一个观察:似乎关于这个主题的大部分讨论表明问题在于 Capybara 需要位于 spec/features 文件夹中的测试才能访问 URL 帮助程序 - 但我的 authentication_pages_spec.rb 文件似乎没有问题与“访问”。

欣赏任何见解!Rails 4.0 的 Rails 教程处于测试阶段,一直试图找出这是否是一个错误。

* 更新 *

执行彼得的建议后,一切顺利。以下是 authentication_pages_spec 文件中的修改代码(部分,只是“授权”部分):

  describe "authorization", type: :request do

    .
    .
    .

    describe "as wrong user" do
      let(:user) { FactoryGirl.create(:user) }
      let(:wrong_user) {FactoryGirl.create(:user, email: "wrong@example.com") }
      before { sign_in user, no_capybara: true }

      describe "visiting Users#edit page" do
        before { visit edit_user_path(wrong_user) }
        it { should_not have_title(full_title('Edit user')) }
      end

      describe "submitting a PATCH request to the Users#update action" do
        before { patch user_path(wrong_user) }
        #  NOTE:  Rails Tutorial uses root_url below not root_path
        specify { expect(response).to redirect_to(root_path) }
      end
    end
  end
end

get, put,patch等仅针对:controllerand :requestspecs 定义,而不是针对规范定义,当您更改其位置时:feature,您的测试隐含地变成了规范。authentication_pages_spec.rb如果你包含type: :request在你的顶层describe,它应该可以工作。

4

2 回答 2

9

get, put,patch等仅针对:controllerand :requestspecs 定义,而不是针对规范定义,当您更改其位置时:feature,您的测试隐含地变成了规范。authentication_pages_spec.rb如果你包含type: :request在你的顶层describe,它应该可以工作。

于 2013-08-17T15:16:11.130 回答
0

这个答案还修复了这个 rspec 测试失败且没有错误的问题,这是 Rails 教程第 9 章的一部分(spec/requests/authentication_pages_spec.rb)

    describe "submitting to the update action" do

      before { patch user_path(user) }

      specify { response.should redirect_to(signin_path) }

    end
于 2014-08-08T20:47:18.813 回答