Create a rescue_from matcher for ActionController
This matcher tests that the controller has been set up to rescue from a specific exception with the ActiveSupport::Rescuable#rescue_from method. It supports checking for a specific method as well.
This commit is contained in:
parent
718c8b6dd0
commit
1b5e3abdf9
4
NEWS.md
4
NEWS.md
|
@ -1,5 +1,9 @@
|
|||
# HEAD
|
||||
|
||||
* Add a rescue_from matcher for Rails controllers which checks that the correct
|
||||
ActiveSupport call has been made and that the handlers exist without actually
|
||||
throwing an exception.
|
||||
|
||||
* Changed the scope of AssociationMatcher methods from protected to private.
|
||||
|
||||
* Extracted `#order`, `#through`, and `#dependent` from AssociationMatcher as
|
||||
|
|
|
@ -61,6 +61,7 @@ describe PostsController, "#show" do
|
|||
it { should respond_with(:success) }
|
||||
it { should render_template(:show) }
|
||||
it { should_not set_the_flash }
|
||||
it { should rescue_from(ActiveRecord::RecordNotFound).with(:render_404) }
|
||||
end
|
||||
end
|
||||
```
|
||||
|
|
|
@ -6,6 +6,7 @@ require 'shoulda/matchers/action_controller/set_session_matcher'
|
|||
require 'shoulda/matchers/action_controller/route_matcher'
|
||||
require 'shoulda/matchers/action_controller/redirect_to_matcher'
|
||||
require 'shoulda/matchers/action_controller/render_template_matcher'
|
||||
require 'shoulda/matchers/action_controller/rescue_from_matcher'
|
||||
|
||||
module Shoulda
|
||||
module Matchers
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
module Shoulda
|
||||
module Matchers
|
||||
module ActionController
|
||||
def rescue_from(exception)
|
||||
RescueFromMatcher.new exception
|
||||
end
|
||||
|
||||
class RescueFromMatcher
|
||||
def initialize(exception)
|
||||
@exception = exception
|
||||
end
|
||||
|
||||
def with(method)
|
||||
@expected_method = method
|
||||
self
|
||||
end
|
||||
|
||||
def matches?(controller)
|
||||
@controller = controller
|
||||
rescues_from_exception? && method_name_matches? && handler_exists?
|
||||
end
|
||||
|
||||
def description
|
||||
description = "rescues from #{exception}"
|
||||
description << " with ##{expected_method}" if expected_method
|
||||
description
|
||||
end
|
||||
|
||||
def failure_message_for_should
|
||||
"Expected #{expectation}"
|
||||
end
|
||||
|
||||
def failure_message_for_should_not
|
||||
"Did not expect #{expectation}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :controller, :exception, :expected_method, :handlers
|
||||
|
||||
def expectation
|
||||
expectation = "#{controller} to rescue from #{exception}"
|
||||
|
||||
if expected_method && !method_name_matches?
|
||||
expectation << " with ##{expected_method}"
|
||||
end
|
||||
|
||||
unless handler_exists?
|
||||
expectation << " but #{controller} does not respond to #{expected_method}"
|
||||
end
|
||||
expectation
|
||||
end
|
||||
|
||||
def rescues_from_exception?
|
||||
@handlers = controller.rescue_handlers.select do |handler|
|
||||
handler.first == exception.to_s
|
||||
end
|
||||
handlers.any?
|
||||
end
|
||||
|
||||
def method_name_matches?
|
||||
if expected_method.present?
|
||||
handlers.any? do |handler|
|
||||
handler.last == expected_method
|
||||
end
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def handler_exists?
|
||||
if expected_method.present?
|
||||
controller.respond_to? expected_method
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,63 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Shoulda::Matchers::ActionController::RescueFromMatcher do
|
||||
context 'a controller that rescues from RuntimeError' do
|
||||
it "asserts controller is setup with rescue_from" do
|
||||
controller_with_rescue_from.should rescue_from RuntimeError
|
||||
end
|
||||
|
||||
context 'with a handler method' do
|
||||
it "asserts rescue_from was set up with handler method" do
|
||||
controller_with_rescue_from_and_method.should rescue_from(RuntimeError).with(:error_method)
|
||||
end
|
||||
|
||||
it "asserts rescue_from was not set up with incorrect handler method" do
|
||||
controller_with_rescue_from_and_method.should_not rescue_from(RuntimeError).with(:other_method)
|
||||
end
|
||||
|
||||
it "asserts the controller responds to the handler method" do
|
||||
matcher = rescue_from(RuntimeError).with(:error_method)
|
||||
matcher.matches?(controller_with_rescue_from_and_invalid_method).should be_false
|
||||
matcher.failure_message_for_should.should =~ /does not respond to/
|
||||
end
|
||||
end
|
||||
|
||||
context 'without a handler method' do
|
||||
it "the handler method is not included in the description" do
|
||||
matcher = rescue_from(RuntimeError)
|
||||
matcher.matches?(controller_with_rescue_from).should be_true
|
||||
matcher.description.should_not =~ /with #/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'a controller that does not rescue from RuntimeError' do
|
||||
it "asserts controller is not setup with rescue_from" do
|
||||
matcher = rescue_from RuntimeError
|
||||
define_controller("RandomController").should_not matcher
|
||||
matcher.failure_message_for_should_not.should =~ /Did not expect \w+ to rescue from/
|
||||
end
|
||||
end
|
||||
|
||||
def controller_with_rescue_from
|
||||
define_controller "RescueRuntimeError" do
|
||||
rescue_from(RuntimeError) {}
|
||||
end
|
||||
end
|
||||
|
||||
def controller_with_rescue_from_and_invalid_method
|
||||
define_controller "RescueRuntimeErrorWithMethod" do
|
||||
rescue_from RuntimeError, with: :error_method
|
||||
end
|
||||
end
|
||||
|
||||
def controller_with_rescue_from_and_method
|
||||
controller = controller_with_rescue_from_and_invalid_method
|
||||
class << controller
|
||||
def error_method
|
||||
true
|
||||
end
|
||||
end
|
||||
controller
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue