Permalink
Browse files

and_raise more closely matches Kernel#raise

* Closes #177
  • Loading branch information...
1 parent dcc92e9 commit 1bd602ff3f7eb9dcce1006a9d1056903279bee55 @basvodde basvodde committed with alindeman Aug 23, 2012
Showing with 49 additions and 49 deletions.
  1. +6 −0 Changelog.md
  2. +13 −19 lib/rspec/mocks/message_expectation.rb
  3. +30 −30 spec/rspec/mocks/mock_spec.rb
View
@@ -1,6 +1,12 @@
### dev
[full changelog](http://github.com/rspec/rspec-mocks/compare/v2.11.2...master)
+Enhancements
+
+* and_raise can accept an exception class and message, more closely
+ matching Kernel#raise (e.g., foo.stub(:bar).and_raise(RuntimeError, "message"))
+ (Bas Vodde)
+
Bug fixes
* Fix `:transfer_nested_constants` option of `stub_const` so that it
@@ -99,24 +99,31 @@ def and_return(*values, &implementation)
# @overload and_raise
# @overload and_raise(ExceptionClass)
+ # @overload and_raise(ExceptionClass, message)
# @overload and_raise(exception_instance)
#
# Tells the object to raise an exception when the message is received.
#
# @note
#
# When you pass an exception class, the MessageExpectation will raise
- # an instance of it, creating it with `new`. If the exception class
- # initializer requires any parameters, you must pass in an instance and
- # not the class.
+ # an instance of it, creating it with `exception` and passing `message`
+ # if specified. If the exception class initializer requires more than
+ # one parameters, you must pass in an instance and not the class,
+ # otherwise this method will raise an ArgumentError exception.
#
# @example
#
# car.stub(:go).and_raise
# car.stub(:go).and_raise(OutOfGas)
+ # car.stub(:go).and_raise(OutOfGas, "At least 2 oz of gas needed to drive")
# car.stub(:go).and_raise(OutOfGas.new(2, :oz))
- def and_raise(exception=RuntimeError)
- @exception_to_raise = exception
+ def and_raise(exception = RuntimeError, message = nil)
+ if exception.respond_to?(:exception)
+ @exception_to_raise = message ? exception.exception(message) : exception.exception
+ else
+ @exception_to_raise = exception
+ end
end
# @overload and_throw(symbol)
@@ -167,7 +174,7 @@ def invoke(*args, &block)
@order_group.handle_order_constraint self
begin
- raise_exception unless @exception_to_raise.nil?
+ raise(@exception_to_raise) unless @exception_to_raise.nil?
Kernel::throw(*@args_to_throw) unless @args_to_throw.empty?
default_return_val = call_with_yield(&block) if !@args_to_yield.empty? || @eval_context
@@ -185,19 +192,6 @@ def invoke(*args, &block)
end
# @private
- def raise_exception
- if !@exception_to_raise.respond_to?(:instance_method) ||
- @exception_to_raise.instance_method(:initialize).arity <= 0
- raise(@exception_to_raise)
- else
- raise ArgumentError.new(<<-MESSAGE)
-'and_raise' can only accept an Exception class if an instance can be constructed with no arguments.
-#{@exception_to_raise.to_s}'s initialize method requires #{@exception_to_raise.instance_method(:initialize).arity} arguments, so you have to supply an instance instead.
-MESSAGE
- end
- end
-
- # @private
def called_max_times?
@expected_received_count != :any &&
!@at_least &&
@@ -214,49 +214,49 @@ def @double.method_with_default_argument(arg={}); end
)
end
- it "raises when told to" do
- @double.should_receive(:something).and_raise(StandardError)
- expect { @double.something }.to raise_error(StandardError)
- end
-
it "raises RuntimeError by default" do
@double.should_receive(:something).and_raise
expect { @double.something }.to raise_error(RuntimeError)
end
- it "raises instance of submitted Exception" do
- error = RuntimeError.new("error message")
- @double.should_receive(:something).and_raise(error)
- lambda {
- @double.something
- }.should raise_error(RuntimeError, "error message")
+ it "raises RuntimeError with a message by default" do
+ @double.should_receive(:something).and_raise("error message")
+ expect { @double.something }.to raise_error(RuntimeError, "error message")
end
- it "raises instance of submitted ArgumentError" do
- error = ArgumentError.new("error message")
- @double.should_receive(:something).and_raise(error)
- lambda {
- @double.something
- }.should raise_error(ArgumentError, "error message")
+ it "raises an exception of a given type without an error message" do
+ @double.should_receive(:something).and_raise(StandardError)
+ expect { @double.something }.to raise_error(StandardError)
end
- it "fails with helpful message if submitted Exception requires constructor arguments" do
- class ErrorWithNonZeroArgConstructor < RuntimeError
- def initialize(i_take_an_argument)
- end
- end
+ it "raises an exception of a given type with a message" do
+ @double.should_receive(:something).and_raise(RuntimeError, "error message")
+ expect { @double.something }.to raise_error(RuntimeError, "error message")
+ end
- @double.stub(:something).and_raise(ErrorWithNonZeroArgConstructor)
- lambda {
- @double.something
- }.should raise_error(ArgumentError, /^'and_raise' can only accept an Exception class if an instance/)
+ it "raises a given instance of an exception" do
+ @double.should_receive(:something).and_raise(RuntimeError.new("error message"))
+ expect { @double.something }.to raise_error(RuntimeError, "error message")
end
- it "raises RuntimeError with submitted message" do
- @double.should_receive(:something).and_raise("error message")
- lambda {
+ class OutOfGas < StandardError
+ attr_reader :amount, :units
+ def initialize(amount, units)
+ @amount = amount
+ @units = units
+ end
+ end
+
+ it "raises a given instance of an exception with arguments other than the standard 'message'" do
+ @double.should_receive(:something).and_raise(OutOfGas.new(2, :oz))
+
+ begin
@double.something
- }.should raise_error(RuntimeError, "error message")
+ fail "OutOfGas was not raised"
+ rescue OutOfGas => e
+ e.amount.should == 2
+ e.units.should == :oz
+ end
end
it "does not raise when told to if args dont match" do

0 comments on commit 1bd602f

Please sign in to comment.