Permalink
Browse files

Fix bug: Message expectation counts don't work in combination with a …

…stub

- Closes #28.
- Closes #33.
  • Loading branch information...
1 parent 866f34a commit dc1044a8aa0dc0c0989f66e882d565f704ba0647 @dnurzynski dnurzynski committed with dchelimsky Jan 16, 2011
Showing with 82 additions and 13 deletions.
  1. +13 −3 lib/rspec/mocks/message_expectation.rb
  2. +1 −0 lib/rspec/mocks/proxy.rb
  3. +68 −10 spec/rspec/mocks/multiple_return_value_spec.rb
@@ -24,6 +24,7 @@ def initialize(error_generator, expectation_ordering, expected_from, sym, method
@order_group = expectation_ordering
@at_least = nil
@at_most = nil
+ @exactly = nil
@args_to_yield = []
@failed_fast = nil
@args_to_yield_were_cloned = false
@@ -286,13 +287,13 @@ def never
def once(&block)
@method_block = block if block
- @expected_received_count = 1
+ set_expected_received_count :exactly, 1
self
end
def twice(&block)
@method_block = block if block
- @expected_received_count = 2
+ set_expected_received_count :exactly, 2
self
end
@@ -307,10 +308,19 @@ def negative_expectation_for?(sym)
return false
end
+ def actual_received_count_matters?
+ @at_least || @at_most || @exactly
+ end
+
+ def increase_actual_received_count!
+ @actual_received_count += 1
+ end
+
protected
def set_expected_received_count(relativity, n)
@at_least = (relativity == :at_least)
@at_most = (relativity == :at_most)
+ @exactly = (relativity == :exactly)
@expected_received_count = case n
when Numeric
n
@@ -324,7 +334,7 @@ def set_expected_received_count(relativity, n)
def clear_actual_received_count!
@actual_received_count = 0
end
-
+
end
class NegativeMessageExpectation < MessageExpectation
@@ -96,6 +96,7 @@ def message_received(method_name, *args, &block)
stub = find_matching_method_stub(method_name, *args)
if (stub && expectation && expectation.called_max_times?) || (stub && !expectation)
+ expectation.increase_actual_received_count! if expectation && expectation.actual_received_count_matters?
if expectation = find_almost_matching_expectation(method_name, *args)
expectation.advise(*args) unless expectation.expected_messages_received?
end
@@ -8,7 +8,7 @@ module Mocks
@return_values = ["1",2,Object.new]
@mock.should_receive(:message).and_return(@return_values[0],@return_values[1],@return_values[2])
end
-
+
it "returns values in order to consecutive calls" do
@mock.message.should == @return_values[0]
@mock.message.should == @return_values[1]
@@ -20,7 +20,7 @@ module Mocks
@mock.message.should == @return_values[0]
@mock.message.should == @return_values[1]
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 2 times|
)
end
@@ -31,10 +31,19 @@ module Mocks
@mock.message.should == @return_values[2]
@mock.message.should == @return_values[2]
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 4 times|
)
end
+
+ it "doesn't complain when there are too many calls but method is stubbed too" do
+ @mock.stub(:message).and_return :stub_result
+ @mock.message.should == @return_values[0]
+ @mock.message.should == @return_values[1]
+ @mock.message.should == @return_values[2]
+ @mock.message.should == :stub_result
+ expect { @mock.rspec_verify }.to_not raise_error(RSpec::Mocks::MockExpectationError)
+ end
end
describe "a Mock expectation with multiple return values with a specified count equal to the number of values" do
@@ -56,7 +65,7 @@ module Mocks
@mock.message.should == @return_values[0]
@mock.message.should == @return_values[1]
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 2 times|
)
end
@@ -68,7 +77,20 @@ module Mocks
@mock.message.should == @return_values[2]
@mock.message.should == @return_values[2]
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
+ %Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 4 times|
+ )
+ end
+
+ it "complains when there are too many calls and method is stubbed too" do
+ third = Object.new
+ @mock.stub(:message).and_return :stub_result
+ @mock.message.should == @return_values[0]
+ @mock.message.should == @return_values[1]
+ @mock.message.should == @return_values[2]
+ @mock.message.should == :stub_result
+ expect { @mock.rspec_verify }.to raise_error(
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 4 times|
)
end
@@ -79,7 +101,7 @@ module Mocks
@mock = RSpec::Mocks::Mock.new("mock")
@mock.should_receive(:message).at_least(:twice).with(no_args).and_return(11, 22)
end
-
+
it "uses the last return value for subsequent calls" do
@mock.message.should equal(11)
@mock.message.should equal(22)
@@ -90,18 +112,38 @@ module Mocks
it "fails when called less than the specified number" do
@mock.message.should equal(11)
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(no args)\n expected: 2 times\n received: 1 time|
)
end
+
+ context "when method is stubbed too" do
+ before { @mock.stub(:message).and_return :stub_result }
+
+ it "uses the stub return value for subsequent calls" do
+ @mock.message.should equal(11)
+ @mock.message.should equal(22)
+ @mock.message.should equal(:stub_result)
+ @mock.rspec_verify
+ end
+
+ it "fails when called less than the specified number" do
+ @mock.message.should equal(11)
+ expect { @mock.rspec_verify }.to raise_error(
+ RSpec::Mocks::MockExpectationError,
+ %Q|(Mock "mock").message(no args)\n expected: 2 times\n received: 1 time|
+ )
+ end
+ end
+
end
describe "a Mock expectation with multiple return values with a specified count larger than the number of values" do
before(:each) do
@mock = RSpec::Mocks::Mock.new("mock")
@mock.should_receive(:message).exactly(3).times.and_return(11, 22)
end
-
+
it "uses the last return value for subsequent calls" do
@mock.message.should equal(11)
@mock.message.should equal(22)
@@ -112,7 +154,7 @@ module Mocks
it "fails when called less than the specified number" do
@mock.message.should equal(11)
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 1 time|
)
end
@@ -123,10 +165,26 @@ module Mocks
@mock.message.should equal(22)
@mock.message.should equal(22)
expect { @mock.rspec_verify }.to raise_error(
- RSpec::Mocks::MockExpectationError,
+ RSpec::Mocks::MockExpectationError,
%Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 4 times|
)
end
+
+ context "when method is stubbed too" do
+ before { @mock.stub(:message).and_return :stub_result }
+
+ it "fails when called greater than the specified number" do
+ @mock.message.should equal(11)
+ @mock.message.should equal(22)
+ @mock.message.should equal(22)
+ @mock.message.should equal(:stub_result)
+ expect { @mock.rspec_verify }.to raise_error(
+ RSpec::Mocks::MockExpectationError,
+ %Q|(Mock "mock").message(any args)\n expected: 3 times\n received: 4 times|
+ )
+ end
+
+ end
end
end
end

0 comments on commit dc1044a

Please sign in to comment.