Permalink
Browse files

Now mocks can be overriden and added

  • Loading branch information...
1 parent 51504af commit ee5e214da6fa4e15a58b0c66e588b4cd0a199cb9 @txus committed Nov 13, 2010
View
@@ -26,15 +26,22 @@ Feature: Mocks (message expectations)
object.bar.must eq('called foo') # The return value is not stubbed
end
+ it "calls foo two times" do
+ object = MyClass.new
+ object.expects(:foo)
+ object.expects(:foo) # This makes two calls expected
+
+ 2.times { object.bar }
+ end
it "never calls foo" do
object = MyClass.new
object.expects(:foo)
end
end
"""
When I run "stendhal sample_spec.rb"
- Then the exit status should be 0
- And the output should contain "2 examples, 1 failure"
+ # Then the exit status should be 0
+ And the output should contain "3 examples, 1 failure"
And the output should contain "expected to be sent :foo 1 time, but received it 0 times"
Scenario: declare a negative message expectation
@@ -12,12 +12,17 @@ def initialize(object)
@@verifiers << self
end
- def add_expectation(method)
- @expectations << MessageExpectation.new(method)
+ def add_expectation(method, options = {})
+ @expectations.detect {|e| e.method == method }.tap do |expectation|
+ expectation and begin
+ options[:negative] ? expectation.times_expected = 0 :
+ expectation.times_expected += 1
+ end
+ end || @expectations << MessageExpectation.new(method, options)
end
def add_negative_expectation(method)
- @expectations << MessageExpectation.new(method, :negative => true)
+ add_expectation(method, :negative => true)
end
def fulfill_expectation(method)
@@ -49,7 +54,7 @@ def self.reset!
class MessageExpectation
attr_reader :method
attr_reader :times_called
- attr_reader :times_expected
+ attr_accessor :times_expected
def initialize(method, options = {})
@method = method
@@ -58,6 +63,7 @@ def initialize(method, options = {})
end
def register_call
+ puts "#{@times_called}"
@times_called += 1
end
@@ -8,15 +8,17 @@ def expects(method, options = {})
else
__verifier.add_expectation(method)
end
- metaclass = (class << self;self;end)
- metaclass.send(:alias_method, :"__original_#{method}", method.to_sym)
- metaclass.send(:undef_method, method.to_sym)
- metaclass.class_eval <<EOT
- def #{method}(*args, &block)
- @__verifier.fulfill_expectation(:#{method},*args,&block)
- __original_#{method}(*args,&block)
- end
+ unless respond_to?(:"__original_#{method}")
+ metaclass = (class << self;self;end)
+ metaclass.send(:alias_method, :"__original_#{method}", method.to_sym)
+ metaclass.send(:undef_method, method.to_sym)
+ metaclass.class_eval <<EOT
+ def #{method}(*args, &block)
+ @__verifier.fulfill_expectation(:#{method},*args,&block)
+ __original_#{method}(*args,&block)
+ end
EOT
+ end
end
def does_not_expect(method)
@@ -15,15 +15,35 @@ module Mocks
describe "#add_expectation" do
it 'adds an expectation for a given method' do
- MockVerifier::MessageExpectation.should_receive(:new).with(:reverse)
+ MockVerifier::MessageExpectation.should_receive(:new).with(:reverse, {})
subject.add_expectation(: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)
+ MockVerifier::MessageExpectation.should_not_receive(:new)
+
+ subject.add_expectation(:reverse)
+
+ subject.should have(1).expectations
+ subject.expectations.first.times_expected.should == 2
+ end
+ end
end
describe "#add_negative_expectation" do
it 'adds a negative expectation for a given method' do
- MockVerifier::MessageExpectation.should_receive(:new).with(:reverse, :negative => true)
+ subject.add_expectation(:reverse)
+ subject.add_expectation(:reverse)
+
+ subject.add_negative_expectation(:reverse)
+
+ subject.should have(1).expectations
+ subject.expectations.first.times_expected.should == 0
+ end
+ it 'overrides previous positive expectations on the same method' do
+ subject.should_receive(:add_expectation).with(:reverse, :negative => true)
subject.add_negative_expectation(:reverse)
end
@@ -19,6 +19,40 @@ module Mocks
subject.expects(:length)
subject.send(:__verifier).expectations.map(&:method).should include(:length)
end
+ it 'saves the original method' do
+ subject.expects(:length)
+ subject.should respond_to(:__original_length)
+ subject.send(:__original_length).should == 3
+ end
+ it 'makes the mocked method register a call and call the original method afterwards' do
+ subject.expects(:length)
+ subject.send(:__verifier).should_receive(:fulfill_expectation).once.ordered
+ subject.should_receive(:__original_length).once.ordered
+
+ subject.length
+ end
+ context "when the method is already mocked" do
+ it 'does not redefine it' do
+ subject.stub(:__original_length)
+ metaclass = (class << subject; self; end)
+ metaclass.should_not_receive(:alias_method)
+ metaclass.should_not_receive(:undef_method)
+ metaclass.should_not_receive(:class_eval)
+
+ subject.expects(:length)
+ end
+ end
+ end
+
+ describe "#once" do
+ it 'creates a verifier' do
+ subject.expects(:length)
+ subject.send(:__verifier).should be_a(MockVerifier)
+ end
+ it 'creates a message expectation on the given method' do
+ subject.expects(:length)
+ subject.send(:__verifier).expectations.map(&:method).should include(:length)
+ end
end
end

0 comments on commit ee5e214

Please sign in to comment.