预期 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 驱动的)而不是功能测试中确实可以更好地测试。

如果您坚持在功能测试中对此进行测试,那么您需要验证一些事项

  1. 确保您在测试环境中没有任何 gem 正在捕获错误并生成 nice/detailed 错误页面。这将包括 web_consolebetter_errors 等 gem。这些 gem 应该只在开发环境中。

  2. 确保您已在测试配置中设置 Capybara.raise_server_errors = true

  3. 您可能需要在块中添加第二个 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)