简体   繁体   中英

Testing sidekiq WebUI reachability in Rails4/Capybara/Rspec3

I'm currently moving some feature tests from Minitest to RSpec. My last problem is with reaching the Sidekiq WebUI which I enabled in my routes.rb

require 'sidekiq/web'
require 'admin_constraint'

Rails.application.routes.draw do
  mount Sidekiq::Web => '/sidekiq', constraints: AdminConstraint.new
  ...
end

The ressource is admin-only protected, which I now want to test. I have two questions

1) Contemplating about the test again made me think, whether it would be better formulated as a routing test. What do you think? Keep in mind that it routes to an external Engine which might make it kinda more complicated. The feature test seemed an easy way around this (simply test whether the ressource is reachable).

2) In Minitest I could do eg the following, which was working fine

require_relative '../test_helper'

feature 'Sidekiq dashboard' do
  scenario 'Dashboard cannot be reached as guest user' do
    assert_raise ActionController::RoutingError do
      visit sidekiq_web_path
    end
  end

  scenario 'Dashboard cannot be reached as regular user' do
    login_as_user

    assert_raise ActionController::RoutingError do
      visit sidekiq_web_path
    end
  end

  scenario 'Dashboard can be reached as admin' do
    login_as_admin
    assert_nothing_raised do
      visit sidekiq_web_path
    end
  end
end

I tried to convert it to RSpec directly like so

scenario 'Dashboard can be reached as user' do
  login_as_user

  expect {
    visit sidekiq_web_path
  }.to raise_error(ActionController::RoutingError)
end

which produces the following error

Failures:

  1) Sidekiq dashboard Dashboard cannot be reached as regular user
     Got 1 failure and 1 other error:

     1.1) Failure/Error:
            expect {
              visit sidekiq_web_path
            }.to raise_error(ActionController::RoutingError)

            expected ActionController::RoutingError but nothing was raised
          # ./spec/features/sidekiq_monitoring_spec.rb:12:in `block (2 levels) in <top (required)>'

     1.2) Failure/Error: raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"

          ActionController::RoutingError:
            No route matches [GET] "/sidekiq"
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/railties-4.2.7.1/lib/rails/rack/logger.rb:38:in `call_app'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/railties-4.2.7.1/lib/rails/rack/logger.rb:20:in `block in call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/railties-4.2.7.1/lib/rails/rack/logger.rb:20:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/request_store-1.3.2/lib/request_store/middleware.rb:9:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/methodoverride.rb:22:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/runtime.rb:18:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/lock.rb:17:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/sendfile.rb:113:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/railties-4.2.7.1/lib/rails/engine.rb:518:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/railties-4.2.7.1/lib/rails/application.rb:165:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/urlmap.rb:66:in `block in call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/urlmap.rb:50:in `each'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/urlmap.rb:50:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/capybara-2.12.0/lib/capybara/server.rb:43:in `call'
          # /home/blubber/.rvm/gems/ruby-2.3.1/gems/rack-1.6.5/lib/rack/handler/webrick.rb:88:in `service'
          # ------------------
          # --- Caused by: ---
          # Capybara::CapybaraError:
          #   Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true
          #   /home/blubber/.rvm/gems/ruby-2.3.1/gems/capybara-2.12.0/lib/capybara/session.rb:129:in `raise_server_error!'

Why does this not work in RSpec?

Thanks in advance, all the best, Andi

When testing with a JS capable driver (poltergeist, etc) Capybara runs the app in a separate server thread. Because of that errors raised in the app don't automatically get seen in the test code. To overcome that Capybara stores any errors raised in the server and, due to the asynchronous nature of commands when using a JS capable driver, re-raises them in the test code the next time it attempts to interact with Capybara. Because of that you would need to have a second interaction inside the block you expect to raise the error

expect {
  visit sidekiq_web_path
  expect(page).to have_text("Something")  # the error will actually raise here
}.to raise_error(ActionController::RoutingError)

I have no clue why it was working for you like that with minitest, and would have to go look at the Minitest code to attempt to figure out why. I would expect your tests to have worked correctly if you were running those tests with the rack_test driver since it doesn't run a separate thread and just calls directly into the app (you claim not to have changed that though).

Note: This really isn't the sort of thing that you should be checking in a feature test, instead it would be better to check for what is displayed on the page when permission is denied/allowed instead of a specific error class that is raised

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM