Permalink
Browse files

Mocks can expect once, twice or exactly n times a method

  • Loading branch information...
txus committed Nov 13, 2010
1 parent ee5e214 commit 61b3d5eb73e570a158f6f58b3c03663fe70c77c0
View
@@ -100,31 +100,19 @@ Feature: Mocks (message expectations)
object.expects(:foo).twice
object.bar
+ object.bar
end
it "calls foo three times" do
object = MyClass.new
object.expects(:foo).exactly(3).times
- 3.times { object.bar }
- end
- it "calls foo at least two times" do
- object = MyClass.new
- object.expects(:foo).at_least(2).times
-
- 3.times { object.bar }
- end
- it "calls foo at most two times" do
- object = MyClass.new
- object.expects(:foo).at_most(2).times
-
3.times { object.bar }
end
end
"""
When I run "stendhal sample_spec.rb"
Then the exit status should be 0
- And the output should contain "4 examples, 1 failure"
- And the output should contain "expected to be sent :foo at most 2 times, but received it 3 times"
+ And the output should contain "2 examples, 0 failures"
Scenario: declare a message expectation stubbing the return value
Given a directory named "stendhal_project"
@@ -5,15 +5,23 @@ class MockVerifier
@@verifiers = []
attr_reader :expectations
+ attr_reader :last_mocked_method
+ attr_reader :object
def initialize(object)
@expectations = []
@object = object
+ @last_mocked_method = nil
@@verifiers << self
end
+ def expectation_for(method)
+ @expectations.detect {|e| e.method == method }
+ end
+
def add_expectation(method, options = {})
- @expectations.detect {|e| e.method == method }.tap do |expectation|
+ @last_mocked_method = method
+ expectation_for(method).tap do |expectation|
expectation and begin
options[:negative] ? expectation.times_expected = 0 :
expectation.times_expected += 1
@@ -19,6 +19,26 @@ def #{method}(*args, &block)
end
EOT
end
+ self
+ end
+
+ def once
+ __verifier.expectation_for(__verifier.last_mocked_method).times_expected = 1
+ self
+ end
+
+ def twice
+ __verifier.expectation_for(__verifier.last_mocked_method).times_expected = 2
+ self
+ end
+
+ def exactly(times)
+ __verifier.expectation_for(__verifier.last_mocked_method).times_expected = times
+ self
+ end
+
+ def times
+ self
end
def does_not_expect(method)
@@ -12,13 +12,27 @@ module Mocks
end
describe "instance methods" do
-
+
+ describe "#expectation_for(method)" do
+ it 'returns the expectation for a given method' do
+ subject.add_expectation(:length)
+ subject.add_expectation(:class)
+
+ subject.expectation_for(:length).should be_a(MockVerifier::MessageExpectation)
+ subject.expectation_for(:length).method.should == :length
+ end
+ end
+
describe "#add_expectation" do
it 'adds an expectation for a given method' do
MockVerifier::MessageExpectation.should_receive(:new).with(:reverse, {})
subject.add_expectation(:reverse)
end
+ it 'remembers last mocked method' do
+ subject.add_expectation(:reverse)
+ subject.last_mocked_method.should == :reverse
+ end
context "if an expectation for such method already exists" do
it 'adds an expected call to that expectation' do
subject.add_expectation(:reverse)
@@ -42,19 +42,55 @@ module Mocks
subject.expects(:length)
end
end
+ it 'returns itself to allow chaining' do
+ subject.expects(:length).should be_a(MyArray)
+ end
end
- describe "#once" do
- it 'creates a verifier' do
- subject.expects(:length)
- subject.send(:__verifier).should be_a(MockVerifier)
+ describe "times a method is expected to be received" do
+
+ {:once => 1,
+ :twice => 2}.each do |name,times|
+
+ describe "##{times}" do
+ it 'sets the times expected for the mocked method to one' do
+ expectation = double('expectation', :times_expected => 7)
+ subject.send(:__verifier).should_receive(:last_mocked_method).and_return :length
+ subject.send(:__verifier).should_receive(:expectation_for).with(:length).and_return expectation
+ expectation.should_receive(:times_expected=).with(times)
+
+ subject.send(name)
+ end
+ it 'returns itself to allow chaining' do
+ subject.send(:__verifier).stub(:last_mocked_method).and_return :length
+ subject.expects(:length).send(name).should be_a(MyArray)
+ end
+ end
+
end
- it 'creates a message expectation on the given method' do
- subject.expects(:length)
- subject.send(:__verifier).expectations.map(&:method).should include(:length)
+
+ describe "#exactly(number_of_times)" do
+ it 'sets the times expected for the mocked method to the given number' do
+ expectation = double('expectation', :times_expected => 7)
+ subject.send(:__verifier).should_receive(:last_mocked_method).and_return :length
+ subject.send(:__verifier).should_receive(:expectation_for).with(:length).and_return expectation
+ expectation.should_receive(:times_expected=).with(3)
+
+ subject.exactly(3)
+ end
+ it 'returns itself to allow chaining' do
+ subject.send(:__verifier).stub(:last_mocked_method).and_return :length
+ subject.expects(:length).twice.should be_a(MyArray)
+ end
end
- end
+ describe "#times" do
+ it 'returns itself to allow chaining' do
+ subject.expects(:length).times.should be_a(MyArray)
+ end
+ end
+
+ end
end
end
end

0 comments on commit 61b3d5e

Please sign in to comment.