Skip to content

Commit

Permalink
Start working on a fix for #230.
Browse files Browse the repository at this point in the history
  • Loading branch information
myronmarston committed Mar 12, 2013
1 parent 3b1aab9 commit 3e04819
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 5 deletions.
17 changes: 12 additions & 5 deletions lib/rspec/mocks/message_expectation.rb
Expand Up @@ -24,10 +24,11 @@ def initialize(error_generator, expectation_ordering, expected_from, method_doub
@args_to_yield = []
@failed_fast = nil
@eval_context = nil
@implementation = implementation

@initial_implementation_logic = nil
@terminal_implementation_logic = nil

self.inner_implementation_logic = implementation
end

# @private
Expand Down Expand Up @@ -78,7 +79,7 @@ def and_return(*values, &implementation)

if implementation
# TODO: deprecate `and_return { value }`
@implementation = implementation
self.inner_implementation = implementation
else
self.terminal_implementation_logic = AndReturnImplementation.new(values)
end
Expand Down Expand Up @@ -129,7 +130,7 @@ def and_raise(exception = RuntimeError, message = nil)
exception = message ? exception.exception(message) : exception.exception
end

@implementation = Proc.new { raise exception }
self.terminal_implementation_logic = Proc.new { raise exception }
end

# @overload and_throw(symbol)
Expand All @@ -143,7 +144,7 @@ def and_raise(exception = RuntimeError, message = nil)
# car.stub(:go).and_throw(:out_of_gas)
# car.stub(:go).and_throw(:out_of_gas, :level => 0.1)
def and_throw(*args)
@implementation = Proc.new { throw *args }
self.terminal_implementation_logic = Proc.new { throw *args }
end

# Tells the object to yield one or more args to a block when the message
Expand Down Expand Up @@ -279,7 +280,7 @@ def raise_out_of_order_error
# cart.add(Book.new(:isbn => 1934356379))
# # => passes
def with(*args, &block)
@implementation = block if block_given? unless args.empty?
self.inner_implementation_logic = block if block_given? unless args.empty?
@argument_list_matcher = ArgumentListMatcher.new(*args, &block)
self
end
Expand Down Expand Up @@ -431,6 +432,11 @@ def initial_implementation_logic=(logic)
update_implementation
end

def inner_implementation_logic=(logic)
@inner_implementation_logic = logic
update_implementation
end

def terminal_implementation_logic=(logic)
@terminal_implementation_logic = logic
update_implementation
Expand All @@ -439,6 +445,7 @@ def terminal_implementation_logic=(logic)
def update_implementation
@implementation = Implementation.new(
@initial_implementation_logic,
@inner_implementation_logic,
@terminal_implementation_logic
).method(:call)
end
Expand Down
91 changes: 91 additions & 0 deletions spec/rspec/mocks/combining_implementation_instructions_spec.rb
@@ -0,0 +1,91 @@
require 'spec_helper'

module RSpec
module Mocks
describe "Combining implementation instructions" do
it 'can combine and_yield and and_return' do
dbl = double
dbl.stub(:foo).and_yield(5).and_return(3)

expect { |b|
expect(dbl.foo(&b)).to eq(3)
}.to yield_with_args(5)
end

it 'can combine and_yield, a block implementation and and_return when passing a block to `stub`' do
dbl = double
block_called = false
dbl.stub(:foo) { block_called = true }.and_yield(5).and_return(3)

expect { |b|
expect(dbl.foo(&b)).to eq(3)
}.to yield_with_args(5)

expect(block_called).to be_true
end

it 'can combine and_yield, a block implementation and and_return when passing a block to `with`' do
dbl = double
block_called = false
dbl.stub(:foo).with(:arg) { block_called = true }.and_yield(5).and_return(3)

expect { |b|
expect(dbl.foo(:arg, &b)).to eq(3)
}.to yield_with_args(5)

expect(block_called).to be_true
end

it 'can combine and_yield and and_raise' do
dbl = double
dbl.stub(:foo).and_yield(5).and_raise("boom")

expect { |b|
expect {
dbl.foo(&b)
}.to raise_error("boom")
}.to yield_with_args(5)
end

it 'can combine and_yield, a block implementation and and_raise' do
dbl = double
block_called = false
dbl.stub(:foo) { block_called = true }.and_yield(5).and_raise("boom")

expect { |b|
expect {
dbl.foo(&b)
}.to raise_error("boom")
}.to yield_with_args(5)

expect(block_called).to be_true
end

it 'can combine and_yield and and_throw' do
dbl = double
dbl.stub(:foo).and_yield(5).and_throw(:bar)

expect { |b|
expect {
dbl.foo(&b)
}.to throw_symbol(:bar)
}.to yield_with_args(5)
end

it 'can combine and_yield, a block implementation and and_throw' do
dbl = double
block_called = false
dbl.stub(:foo) { block_called = true }.and_yield(5).and_throw(:bar)

expect { |b|
expect {
dbl.foo(&b)
}.to throw_symbol(:bar)
}.to yield_with_args(5)

expect(block_called).to be_true
end
end
end
end

0 comments on commit 3e04819

Please sign in to comment.