预期 ActionController::RoutingError 但未在 rails 应用 rspec 中被阻止
expected ActionController::RoutingError but was not given a block in rails app rspec
我尝试测试我的 RoR 应用程序。当我测试在我的控制器中导致 ActionController::RoutingError 时,我收到以下错误:
出现 1 次失败和 1 次其他错误:
2.1) Failure/Error: expect(visit meters_path).to raise_error(ActionController::RoutingError)
expected ActionController::RoutingError but was not given a block
# ./spec/integration/meter_behavior_spec.rb:70:in `block (2 levels) in <top (required)>'
2.2) Failure/Error: raise ActionController::RoutingError.new('Not Found')
ActionController::RoutingError:
Not Found
这是什么原因?
这是我的测试宝石列表:
group :development, :test do
gem 'factory_girl_rails'
gem 'faker'
gem 'rspec-rails'
end
group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'launchy'
gem 'selenium-webdriver', '2.53.4'
gem 'capybara-webkit'
gem 'shoulda-matchers', '~> 3.1'
end
我的规范文件
meter_behavior_spec.rb
scenario 'a visitor cannot to view meters pages', driver: :webkit do
user = FactoryGirl.create(:client1)
user.meters.create(attributes_for(:meter))
expect(visit meters_path).to raise_error(ActionController::RoutingError)
end
meters_controller.rb:
before_action only: :index do
access_allowed_for(['Client'])
end
# GET /meters
# GET /meters.json
def index
respond_to do |format|
format.json { render json: MetersDatatable.new(view_context, current_user) }
format.html
end
end
application_controller.rb:
def access_allowed_for(statuses_ary=[])
statuses_ary << 'Admin'
if !user_signed_in? || statuses_ary.exclude?(current_user.try(:status))
raise ActionController::RoutingError.new('Not Found')
end
end
我认为您应该简单地将 visit meters_path 作为一个块而不是作为参数传递,就像这样:
expect{visit meters_path}.to raise_error(ActionController::RoutingError)
参见:
https://www.relishapp.com/rspec/rspec-expectations/v/2-2/docs/matchers/expect-error
告诉我它是否有效。
Jean-Christophe 的回答中指出的第一个问题是 raise_error
匹配器需要一个块。第二个问题是你正在测试的东西在控制器测试(不是 Capybara 驱动的)而不是功能测试中确实可以更好地测试。
如果您坚持在功能测试中对此进行测试,那么您需要验证一些事项
确保您在测试环境中没有任何 gem 正在捕获错误并生成 nice/detailed 错误页面。这将包括 web_console
、better_errors
等 gem。这些 gem 应该只在开发环境中。
确保您已在测试配置中设置 Capybara.raise_server_errors = true
您可能需要在块中添加第二个 Capybara 语句。这是因为 Capybara 在与测试不同的线程中运行应用程序,并且访问调用可能异步发生(取决于您使用的驱动程序)。这意味着访问调用 returns 时可能实际上并未引发错误。通过添加对 capybara 方法的第二次调用,它将稍微等待访问完成,然后检测到 server/app 线程中出现错误并在测试线程中重新引发该错误。
expect{
visit meters_path
page.has_text? 'Random text' # only here to give time for app to raise error
}.to raise_error(ActionController::RoutingError)
我尝试测试我的 RoR 应用程序。当我测试在我的控制器中导致 ActionController::RoutingError 时,我收到以下错误: 出现 1 次失败和 1 次其他错误:
2.1) Failure/Error: expect(visit meters_path).to raise_error(ActionController::RoutingError)
expected ActionController::RoutingError but was not given a block
# ./spec/integration/meter_behavior_spec.rb:70:in `block (2 levels) in <top (required)>'
2.2) Failure/Error: raise ActionController::RoutingError.new('Not Found')
ActionController::RoutingError:
Not Found
这是什么原因? 这是我的测试宝石列表:
group :development, :test do
gem 'factory_girl_rails'
gem 'faker'
gem 'rspec-rails'
end
group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'launchy'
gem 'selenium-webdriver', '2.53.4'
gem 'capybara-webkit'
gem 'shoulda-matchers', '~> 3.1'
end
我的规范文件
meter_behavior_spec.rb
scenario 'a visitor cannot to view meters pages', driver: :webkit do
user = FactoryGirl.create(:client1)
user.meters.create(attributes_for(:meter))
expect(visit meters_path).to raise_error(ActionController::RoutingError)
end
meters_controller.rb:
before_action only: :index do
access_allowed_for(['Client'])
end
# GET /meters
# GET /meters.json
def index
respond_to do |format|
format.json { render json: MetersDatatable.new(view_context, current_user) }
format.html
end
end
application_controller.rb:
def access_allowed_for(statuses_ary=[])
statuses_ary << 'Admin'
if !user_signed_in? || statuses_ary.exclude?(current_user.try(:status))
raise ActionController::RoutingError.new('Not Found')
end
end
我认为您应该简单地将 visit meters_path 作为一个块而不是作为参数传递,就像这样:
expect{visit meters_path}.to raise_error(ActionController::RoutingError)
参见:
https://www.relishapp.com/rspec/rspec-expectations/v/2-2/docs/matchers/expect-error
告诉我它是否有效。
Jean-Christophe 的回答中指出的第一个问题是 raise_error
匹配器需要一个块。第二个问题是你正在测试的东西在控制器测试(不是 Capybara 驱动的)而不是功能测试中确实可以更好地测试。
如果您坚持在功能测试中对此进行测试,那么您需要验证一些事项
确保您在测试环境中没有任何 gem 正在捕获错误并生成 nice/detailed 错误页面。这将包括
web_console
、better_errors
等 gem。这些 gem 应该只在开发环境中。确保您已在测试配置中设置
Capybara.raise_server_errors = true
您可能需要在块中添加第二个 Capybara 语句。这是因为 Capybara 在与测试不同的线程中运行应用程序,并且访问调用可能异步发生(取决于您使用的驱动程序)。这意味着访问调用 returns 时可能实际上并未引发错误。通过添加对 capybara 方法的第二次调用,它将稍微等待访问完成,然后检测到 server/app 线程中出现错误并在测试线程中重新引发该错误。
expect{ visit meters_path page.has_text? 'Random text' # only here to give time for app to raise error }.to raise_error(ActionController::RoutingError)