<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/mocha/argument_iterator.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -6,6 +6,7 @@ require 'mocha/mockery'
 require 'mocha/method_matcher'
 require 'mocha/parameters_matcher'
 require 'mocha/unexpected_invocation'
+require 'mocha/argument_iterator'
 
 module Mocha # :nodoc:
   
@@ -15,9 +16,9 @@ module Mocha # :nodoc:
   class Mock
     
     # :call-seq: expects(method_name) -&gt; expectation
-    #            expects(method_names) -&gt; last expectation
+    #            expects(method_names_vs_return_values) -&gt; last expectation
     #
-    # Adds an expectation that a method identified by +method_name+ symbol must be called exactly once with any parameters.
+    # Adds an expectation that a method identified by +method_name+ Symbol/String must be called exactly once with any parameters.
     # Returns the new expectation which can be further modified by methods on Expectation.
     #   object = mock()
     #   object.expects(:method1)
@@ -27,7 +28,7 @@ module Mocha # :nodoc:
     #   object = mock()
     #   object.expects(:method1)
     #   # error raised, because method1 not called exactly once
-    # If +method_names+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+    # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
     #   object = mock()
     #   object.expects(:method1 =&gt; :result1, :method2 =&gt; :result2)
     #
@@ -39,28 +40,27 @@ module Mocha # :nodoc:
     #
     # Aliased by &lt;tt&gt;\_\_expects\_\_&lt;/tt&gt;
     def expects(method_name_or_hash, backtrace = nil)
-      if method_name_or_hash.is_a?(Hash) then
-        method_name_or_hash.each do |method_name, return_value|
-          ensure_method_not_already_defined(method_name)
-          @expectations.add(Expectation.new(self, method_name, backtrace).returns(return_value))
-        end
-      else
-        ensure_method_not_already_defined(method_name_or_hash)
-        @expectations.add(Expectation.new(self, method_name_or_hash, backtrace))
-      end
+      iterator = ArgumentIterator.new(method_name_or_hash)
+      iterator.each { |*args|
+        method_name = args.shift
+        ensure_method_not_already_defined(method_name)
+        expectation = Expectation.new(self, method_name, backtrace)
+        expectation.returns(args.shift) if args.length &gt; 0
+        @expectations.add(expectation)
+      }
     end
     
     # :call-seq: stubs(method_name) -&gt; expectation
-    #            stubs(method_names) -&gt; last expectation
+    #            stubs(method_names_vs_return_values) -&gt; last expectation
     #
-    # Adds an expectation that a method identified by +method_name+ symbol may be called any number of times with any parameters.
+    # Adds an expectation that a method identified by +method_name+ Symbol/String may be called any number of times with any parameters.
     # Returns the new expectation which can be further modified by methods on Expectation.
     #   object = mock()
     #   object.stubs(:method1)
     #   object.method1
     #   object.method1
     #   # no error raised
-    # If +method_names+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+    # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
     #   object = mock()
     #   object.stubs(:method1 =&gt; :result1, :method2 =&gt; :result2)
     #
@@ -72,15 +72,15 @@ module Mocha # :nodoc:
     #
     # Aliased by &lt;tt&gt;\_\_stubs\_\_&lt;/tt&gt;
     def stubs(method_name_or_hash, backtrace = nil)
-      if method_name_or_hash.is_a?(Hash) then
-        method_name_or_hash.each do |method_name, return_value|
-          ensure_method_not_already_defined(method_name)
-          @expectations.add(Expectation.new(self, method_name, backtrace).at_least(0).returns(return_value))
-        end
-      else
-        ensure_method_not_already_defined(method_name_or_hash)
-        @expectations.add(Expectation.new(self, method_name_or_hash, backtrace).at_least(0))
-      end
+      iterator = ArgumentIterator.new(method_name_or_hash)
+      iterator.each { |*args|
+        method_name = args.shift
+        ensure_method_not_already_defined(method_name)
+        expectation = Expectation.new(self, method_name, backtrace)
+        expectation.at_least(0)
+        expectation.returns(args.shift) if args.length &gt; 0
+        @expectations.add(expectation)
+      }
     end
     
     # :call-seq: responds_like(responder) -&gt; mock</diff>
      <filename>lib/mocha/mock.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,7 @@ require 'mocha/instance_method'
 require 'mocha/class_method'
 require 'mocha/module_method'
 require 'mocha/any_instance_method'
+require 'mocha/argument_iterator'
 
 module Mocha
   
@@ -27,42 +28,78 @@ module Mocha
       self
     end
   
-    # :call-seq: expects(symbol) -&gt; expectation
+    # :call-seq: expects(method_name) -&gt; expectation
+    #            expects(method_names_vs_return_values) -&gt; last expectation
     #
-    # Adds an expectation that a method identified by +symbol+ must be called exactly once with any parameters.
+    # Adds an expectation that a method identified by +method_name+ Symbol must be called exactly once with any parameters.
     # Returns the new expectation which can be further modified by methods on Mocha::Expectation.
     #   product = Product.new
     #   product.expects(:save).returns(true)
-    #   assert_equal false, product.save
+    #   assert_equal true, product.save
     #
     # The original implementation of &lt;tt&gt;Product#save&lt;/tt&gt; is replaced temporarily.
     #
     # The original implementation of &lt;tt&gt;Product#save&lt;/tt&gt; is restored at the end of the test.
-    def expects(symbol)
+    #
+    # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+    #   product = Product.new
+    #   product.expects(:valid? =&gt; true, :save =&gt; true)
+    #
+    #   # exactly equivalent to
+    #
+    #   product = Product.new
+    #   product.expects(:valid?).returns(true)
+    #   product.expects(:save).returns(true)
+    def expects(method_name_or_hash)
+      expectation = nil
       mockery = Mocha::Mockery.instance
-      mockery.on_stubbing(self, symbol)
-      method = stubba_method.new(stubba_object, symbol)
-      mockery.stubba.stub(method)
-      mocha.expects(symbol, caller)
+      iterator = ArgumentIterator.new(method_name_or_hash)
+      iterator.each { |*args|
+        method_name = args.shift
+        mockery.on_stubbing(self, method_name)
+        method = stubba_method.new(stubba_object, method_name)
+        mockery.stubba.stub(method)
+        expectation = mocha.expects(method_name, caller)
+        expectation.returns(args.shift) if args.length &gt; 0
+      }
+      expectation
     end
   
-    # :call-seq: stubs(symbol) -&gt; expectation
+    # :call-seq: stubs(method_name) -&gt; expectation
+    #            stubs(method_names_vs_return_values) -&gt; last expectation
     #
-    # Adds an expectation that a method identified by +symbol+ may be called any number of times with any parameters.
+    # Adds an expectation that a method identified by +method_name+ Symbol may be called any number of times with any parameters.
     # Returns the new expectation which can be further modified by methods on Mocha::Expectation.
     #   product = Product.new
     #   product.stubs(:save).returns(true)
-    #   assert_equal false, product.save
+    #   assert_equal true, product.save
     #
     # The original implementation of &lt;tt&gt;Product#save&lt;/tt&gt; is replaced temporarily.
     #
     # The original implementation of &lt;tt&gt;Product#save&lt;/tt&gt; is restored at the end of the test.
-    def stubs(symbol)
+    #
+    # If +method_names_vs_return_values+ is a +Hash+, an expectation will be set up for each entry using the key as +method_name+ and value as +return_value+.
+    #   product = Product.new
+    #   product.stubs(:valid? =&gt; true, :save =&gt; true)
+    #
+    #   # exactly equivalent to
+    #
+    #   product = Product.new
+    #   product.stubs(:valid?).returns(true)
+    #   product.stubs(:save).returns(true)
+    def stubs(method_name_or_hash)
+      expectation = nil
       mockery = Mocha::Mockery.instance
-      mockery.on_stubbing(self, symbol)
-      method = stubba_method.new(stubba_object, symbol)
-      mockery.stubba.stub(method)
-      mocha.stubs(symbol, caller)
+      iterator = ArgumentIterator.new(method_name_or_hash)
+      iterator.each { |*args|
+        method_name = args.shift
+        mockery.on_stubbing(self, method_name)
+        method = stubba_method.new(stubba_object, method_name)
+        mockery.stubba.stub(method)
+        expectation = mocha.stubs(method_name, caller)
+        expectation.returns(args.shift) if args.length &gt; 0
+      }
+      expectation
     end
   
     def method_exists?(method, include_public_methods = true) # :nodoc:</diff>
      <filename>lib/mocha/object.rb</filename>
    </modified>
    <modified>
      <diff>@@ -162,4 +162,42 @@ class StubInstanceMethodTest &lt; Test::Unit::TestCase
     assert_passed(test_result)
   end
   
+  def test_should_be_able_to_specify_expectations_on_multiple_methods_in_a_single_call_to_expects
+    instance = Class.new do
+      def my_instance_method_1
+        :original_return_value_1
+      end
+      def my_instance_method_2
+        :original_return_value_2
+      end
+    end.new
+    run_test do
+      instance.expects(
+        :my_instance_method_1 =&gt; :new_return_value_1,
+        :my_instance_method_2 =&gt; :new_return_value_2
+      )
+      assert_equal :new_return_value_1, instance.my_instance_method_1
+      assert_equal :new_return_value_2, instance.my_instance_method_2
+    end
+  end
+  
+  def test_should_be_able_to_specify_expectations_on_multiple_methods_in_a_single_call_to_stubs
+    instance = Class.new do
+      def my_instance_method_1
+        :original_return_value_1
+      end
+      def my_instance_method_2
+        :original_return_value_2
+      end
+    end.new
+    run_test do
+      instance.stubs(
+        :my_instance_method_1 =&gt; :new_return_value_1,
+        :my_instance_method_2 =&gt; :new_return_value_2
+      )
+      assert_equal :new_return_value_1, instance.my_instance_method_1
+      assert_equal :new_return_value_2, instance.my_instance_method_2
+    end
+  end
+
 end
\ No newline at end of file</diff>
      <filename>test/acceptance/stub_instance_method_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>d4a5b3e2efd5f31cbf5020589503a943a6215e46</id>
    </parent>
  </parents>
  <author>
    <name>James Mead</name>
    <email>james@floehopper.org</email>
  </author>
  <url>http://github.com/sprsquish/mocha/commit/1b3ed16c7755f8a548087d2d31bbcb44e2315281</url>
  <id>1b3ed16c7755f8a548087d2d31bbcb44e2315281</id>
  <committed-date>2008-12-02T09:04:01-08:00</committed-date>
  <authored-date>2008-12-02T09:04:01-08:00</authored-date>
  <message>As Tobias Crawley correctly pointed out in feature request #23055 &quot;stubs(with_hash) not working with existing object&quot; [1], following the principle of least surprise, it should be possible to call ObjectMethods#expects &amp; ObjectMethods#stubs with a Hash of method_names vs return_values like you can with Mock#expects &amp; Mock#stubs. I've extracted out some shared logic into the ArgumentIterator - not sure this is the best solution, but at least it keeps duplication to a minimum. I've also updated &amp; improved the docs to reflect the changes.

[1] http://rubyforge.org/tracker/index.php?func=detail&amp;aid=23055&amp;group_id=1917&amp;atid=7480</message>
  <tree>d26863d4a9380da3d2017154949d11d49085d2c9</tree>
  <committer>
    <name>James Mead</name>
    <email>james@floehopper.org</email>
  </committer>
</commit>
