I try to test my RoR application. When i test to cause ActionController::RoutingError in my controller i get following errors: Got 1 failure and 1 other error:
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
What is the reason? It is my list of testing gems:
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
my spec file
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
The first issue as pointed out in Jean-Christophe's answer is that the raise_error
matcher needs a block. The second issue is you're testing something that would really be better tested in a controller test (not Capybara driven) instead of a feature test.
If you insist on testing this in a feature test then there's a few things you need to verify
Make sure you don't have any gems in the test environment that are catching the errors and producing nice/detailed error pages. This would include gems like web_console
, better_errors
, etc. Those gems should be only in the development environment.
Make sure you have set Capybara.raise_server_errors = true
in your test config
You may need to add a second Capybara statement inside the block. This is because Capybara runs the app in a separate thread from the tests and the visit call may occur asynchronously (depending on the driver you use). That means the error may not have actually been raised when the visit call returns. By adding a second call to a capybara method it will wait a little bit for the visit to finish and then detect that an error was raised in the server/app thread and re-raise that error in the test thread.
expect{
visit meters_path
page.has_text? 'Random text' # only here to give time for app to raise error
}.to raise_error(ActionController::RoutingError)