在 Rails 中使用 RSpec 和 Capybara 时未定义的方法“访问”

Posted

技术标签:

【中文标题】在 Rails 中使用 RSpec 和 Capybara 时未定义的方法“访问”【英文标题】:undefined method `visit' when using RSpec and Capybara in rails 【发布时间】:2013-02-15 09:56:31 【问题描述】:

我无法让 capybara 使用 rspec。它给了我这个错误:

undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 @example=nil>

我知道有很多关于此的帖子,但没有一个解决方案对我有用。它们中的大多数都涉及不在 /spec/features 中的规范 - 我的在其中。

首先是错误:

$bundle exec rspec spec
F

Failures:

  1) security signs users in
     Failure/Error: visit "/sessions/new"
     NoMethodError:
       undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 @example=nil>
     # ./spec/features/security_spec.rb:4:in `(root)'

 Finished in 0.006 seconds
 1 example, 1 failure

Failed examples:

rspec ./spec/features/security_spec.rb:3 # security signs users in

我认为重要的是要注意,起初我使用的是 URL 帮助程序“new_sessions_path”,它一直给我一个错误undefined local variable or method 'new_sessions_path'。我知道它是有效的,因为:

$ rake routes
logout_sessions GET    /sessions/logout(.:format) sessions#logout
       sessions POST   /sessions(.:format)        sessions#create
   new_sessions GET    /sessions/new(.:format)    sessions#new
      contracts POST   /contracts(.:format)       contracts#create
  new_contracts GET    /contracts/new(.:format)   contracts#new
 edit_contracts GET    /contracts/edit(.:format)  contracts#edit
                GET    /contracts(.:format)       contracts#show
                PUT    /contracts(.:format)       contracts#update
                DELETE /contracts(.:format)       contracts#destroy
           root        /                          contracts#index

我的宝石文件:

source 'https://rubygems.org'

gem 'rails', '3.2.11'
gem 'execjs'

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'activerecord-oracle_enhanced-adapter', '~> 1.4.1'
gem 'jruby-openssl'
gem 'therubyrhino'
gem 'kaminari'
gem 'nokogiri'

group :development do
  gem 'warbler'
end

group :test do
  gem 'rspec-rails'
  gem 'capybara'
  gem 'activerecord-jdbcsqlite3-adapter'
end

spec_helper.rb 在 my_app/spec 中:

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

# Capybara integration
require 'capybara/rspec'
require 'capybara/rails'

# 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

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  # config.fixture_path = "#::Rails.root/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"
  # Include path helpers
  config.include Rails.application.routes.url_helpers
end

my_app/spec/features/security_spec.rb:

describe "security", :type => :feature do
  it "signs users in" do
    visit "/sessions/new"
    fill_in "username", :with => "user"
    fill_in "password", :with => "pass"
    click_button "Sign In"

    page.should have_content('Login Successful')
  end
end

我已经尝试在上面定义有:type =&gt; :feature 和没有:type =&gt; :feature 的测试。两种方式都没有区别。有什么想法我接下来应该尝试什么?

【问题讨论】:

Capybara: undefined method 'visit'的可能重复 @mlt 在第一段中我说:“我知道有很多关于此的帖子,但没有一个解决方案对我有用。其中大多数涉及不在 /spec/features 中的规范——我的在哪。”本段专门引用您链接到的问题。这个问题不仅有更高的投票,而且还附带一个解决方案 - 这与您链接问题上发布的最高投票答案(不是解决方案)不同。 【参考方案1】:

尝试添加:

  config.include Capybara::DSL

到您的配置块。

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

# 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

RSpec.configure do |config|
  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  # config.fixture_path = "#::Rails.root/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_base_class_for_anonymous_controllers = false
  config.order = "random"
  # Include path helpers
  config.include Rails.application.routes.url_helpers

  config.include Capybara::DSL

end

【讨论】:

不,完全相同的问题,没有明显变化 这对我有用——非常感谢。尽管在我的其他项目中,我不需要这样做。什么情况下在一个项目中需要这样做,而在另一个项目中不需要?另外,这到底是做什么的? 也为我工作。非常感谢! 我的文件已经有要求'spec_helper',它被检查为这个问题的答案,但这对我有用。谢谢! 这对我不起作用:我收到一条错误消息,指出 Capybara 是一个未定义的常量。我的 Cucumber 测试使用 Capybara 很好。【参考方案2】:

在我的功能顶部添加require 'rails_helper' 最终解决了我的问题:

require 'rails_helper'

describe "security", :type => :feature do

  it "signs users in" do
    visit new_sessions_path
    fill_in "username", :with => "user"
    fill_in "password", :with => "pass"
    click_button "Sign In"

    page.should have_content('Login Successful')
  end
end

这对我来说似乎很奇怪,因为我看到的 rspec 和 capybara 的每个示例都没有这个要求,但是哦,好吧。问题解决了。

原始答案(旧版本的 rspec)

require 'spec_helper' 被旧版本的 RSpec 使用。更好的答案是require 'rails_helper'

【讨论】:

您应该将更新部分放在帖子的顶部。 接受自己的答案真的很糟糕,即使 Kocur4d 的答案更精确(并且忘记包含 rails_helper.rb 不会是更常见的问题)。您应该更改接受的答案,因为在包含它之前没有完成配置更改,您仍然会遇到相同的错误。【参考方案3】:

尝试在 before 块中执行所有设置:

spec/features/security_spec.rb

describe "security" do
  before do
    visit "/sessions/new"
    fill_in "username", :with => "user"
    fill_in "password", :with => "pass"
    click_button "Sign In"
  end

  it "signs users in" do
    page.should have_content('Login Successful')
  end
end

【讨论】:

这实际上是错误的常见原因visit 函数仅在 it 块内可用。 Source 不正确——before 块中的代码在示例上下文中运行,因此visit 将在那里以及it 块中工作。 @user912563,最终,既然你解决了你自己的问题,我的回答真的变成了一种风格建议,而不是其他任何东西(在before 块中设置代码是我编写规范的方式,他们工作没有错误;-)),所以我认为接受你自己的答案是公平的。 感谢@zetetic 和@Paul-Firavanti - 我不知道before 仍然在it 上下文中。使用它将使我的其他需要登录的测试更加干净 这对我很有帮助,因为我是个菜鸟,而且没有包含测试"" do ... end.【参考方案4】:

由于 Capybara 2.0 必须使用文件夹规范/功能 Capybara 命令不再适用于文件夹规范/请求。

【讨论】:

正如我的问题所述,我的水豚测试位于spec/features 下。但这对于可能遇到问题的其他人来说是一个有效的观点。 我发现创建目录mkdir spec/features 并创建符号链接ln -s spec/features spec/requests 很有帮助。这样,任何生成的测试都将放置在 features 目录中。 感谢@ThillaiNarayanan,这是我遵循较旧的设置指南的问题,但在较新的 Capybara 版本上【参考方案5】:

我也有这个问题,

在我的功能顶部添加 require 'rails_helper' 最终解决了我的问题:

require 'rails_helper'

RSpec.describe "Products", type: :request do
 describe "GET /products" do
 it "display tasks" do
  Product.create!(:name => "samsung")
  visit products_path
  page.should have_content("samsung")
  #expect(response).to have_http_status(200)
  end
 end
end

并在 rails_helper.rb 中添加 'config.include Capybara::DSL'

RSpec.configure do |config|

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

 config.use_transactional_fixtures = true

 config.infer_spec_type_from_file_location!

 config.include Capybara::DSL

end

【讨论】:

添加配置行对我有用。这很奇怪,因为我在我的一个规范文件中得到了错误,但在另一个规范文件中没有,并且都调用了相同的 capy 方法(并且都需要 rails_helper)

以上是关于在 Rails 中使用 RSpec 和 Capybara 时未定义的方法“访问”的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 3.1 中使用 Capybara、Rspec 和 Selenium 进行测试时登录失败

如何将内存中的 MongoDB 与 Rails、Mongoid 和 Rspec 一起使用?

rails3, rspec2 ActiveRecord#changes 规格中的错误

Rails 和 RSpec:在不同的命名空间(模块)中测试具有相同名称的控制器

如何使用rails cucumber,rspec,capybara在视图(dhtml)中测试动态部分?

在 Rails 3 上使用 Rspec 和 MongoID 清理或重置测试数据库