【问题标题】:expected ActionController::RoutingError but was not given a block in rails app rspec预期的 ActionController::RoutingError 但在 rails app rspec 中没有给出块
【发布时间】:2017-02-27 11:01:45
【问题描述】:

我尝试测试我的 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

【问题讨论】:

    标签: ruby-on-rails capybara rspec-rails


    【解决方案1】:

    Jean-Christophe 的回答中指出的第一个问题是 raise_error 匹配器需要一个块。第二个问题是您正在测试的东西在控制器测试(不是 Capybara 驱动的)而不是功能测试中会得到更好的测试。

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

    1. 确保您在测试环境中没有任何可以捕获错误并生成漂亮/详细错误页面的 gem。这将包括 web_consolebetter_errors 等 gem。这些 gem 应该只在开发环境中。

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

    3. 您可能需要在块内添加第二条 Capybara 语句。这是因为 Capybara 在与测试不同的线程中运行应用程序,并且访问调用可能异步发生(取决于您使用的驱动程序)。这意味着当访问调用返回时,错误可能实际上并未引发。通过添加对 capybara 方法的第二次调用,它会稍等片刻等待访问完成,然后检测到服务器/应用线程中出现错误并在测试线程中重新引发该错误。

       expect{
         visit meters_path
         page.has_text? 'Random text' # only here to give time for app to raise error
       }.to raise_error(ActionController::RoutingError)
      

    【讨论】:

    • 1 我检查了我的 gemfile 中有 web-console 和“更好的错误” gem,但两者都在 development 组中。 2 然后我将Capybara.raise_server_errors = true 字符串添加到spec/support/capybara.rb 文件中,但再次出现错误。 3 最后我添加了page.has_text? 声明,它有所帮助。谢谢。
    • 当我评论 Capybara.raise_server_errors = true 字符串时,测试任何效果。
    • @ЭрикКеубасов 是的 - 默认为 true,我只是想确保您没有在某处将其重置为 false。
    【解决方案2】:

    我相信你应该简单地将访问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

    告诉我它是否有效。

    【讨论】:

    • 谢谢,但没有帮助。我更正并得到类似的错误:1.1)失败/错误:expect{visit meter_path}.to raise_error(ActionController::RoutingError) 预期 ActionController::RoutingError 但没有引发 1.2)失败/错误:引发 ActionController::RoutingError.new ('未找到')
    • 好吧,不过它正朝着正确的方向发展。现在,第一个失败出现在您正在测试的代码中,而不是您的测试代码中。如果您在控制器操作或 access_allowed_for 方法(即在您的条件之外)中自动引发错误,则测试是否通过。这将排除加注本身的任何问题。至于你的条件,你的 :client1 工厂给你的用户什么状态? (“客户”?“客户”?)
    • 当我在控制器中引发错误时,我会收到类似的失败/错误消息。 client1 具有“客户”状态。还是谢谢你。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2018-10-16
    • 2015-07-17
    • 2014-12-11
    • 1970-01-01
    相关资源
    最近更新 更多