Permalink
Browse files

add multiple call support to minimock per seattlerb#79

[git-p4: depot-paths = "//src/minitest/dev/": change = 6962]
  • Loading branch information...
Steven R. Baker
Steven R. Baker committed Jan 29, 2012
1 parent 57b06f7 commit 88eec1b91843c508f5099b82f99bb4a5a76859a5
Showing with 62 additions and 26 deletions.
  1. +32 −21 lib/minitest/mock.rb
  2. +30 −5 test/test_minitest_mock.rb
View
@@ -19,8 +19,8 @@ class Mock
end
def initialize # :nodoc:
- @expected_calls = {}
- @actual_calls = Hash.new {|h,k| h[k] = [] }
+ @expected_calls = Hash.new { |calls, name| calls[name] = [] }
+ @actual_calls = Hash.new { |calls, name| calls[name] = [] }
end
##
@@ -46,7 +46,7 @@ def initialize # :nodoc:
def expect(name, retval, args=[])
raise ArgumentError, "args must be an array" unless Array === args
- @expected_calls[name] = { :retval => retval, :args => args }
+ @expected_calls[name] << { :retval => retval, :args => args }
self
end
@@ -56,36 +56,47 @@ def expect(name, retval, args=[])
# expected.
def verify
- @expected_calls.each_key do |name|
- expected = @expected_calls[name]
- msg1 = "expected #{name}, #{expected.inspect}"
- msg2 = "#{msg1}, got #{@actual_calls[name].inspect}"
-
- raise MockExpectationError, msg2 if
- @actual_calls.has_key? name and
- not @actual_calls[name].include?(expected)
-
- raise MockExpectationError, msg1 unless
- @actual_calls.has_key? name and @actual_calls[name].include?(expected)
+ @expected_calls.each do |name, calls|
+ calls.each do |expected|
+ msg1 = "expected #{name}, #{expected.inspect}"
+ msg2 = "#{msg1}, got #{@actual_calls[name].inspect}"
+
+ raise MockExpectationError, msg2 if
+ @actual_calls.has_key? name and
+ not @actual_calls[name].include?(expected)
+
+ raise MockExpectationError, msg1 unless
+ @actual_calls.has_key? name and @actual_calls[name].include?(expected)
+ end
end
true
end
def method_missing(sym, *args) # :nodoc:
- expected = @expected_calls[sym]
-
- unless expected then
+ unless @expected_calls.has_key?(sym) then
raise NoMethodError, "unmocked method %p, expected one of %p" %
[sym, @expected_calls.keys.sort_by(&:to_s)]
end
- expected_args, retval = expected[:args], expected[:retval]
+ x_calls = @expected_calls[sym].select { |call| call[:args].size == args.size }
+
+ if x_calls.empty?
+ arg_sizes = @expected_calls[sym].map { |call| call[:args].size }.uniq.sort
+ raise ArgumentError, "mocked method %p expects %s arguments, got %d" %
+ [sym, arg_sizes.join('/'), args.size]
+ end
+
+ x_call = x_calls.find do |call|
+ call[:args].zip(args).all? { |mod, a| mod === a or mod == a }
+ end
- unless expected_args.size == args.size
- raise ArgumentError, "mocked method %p expects %d arguments, got %d" %
- [sym, expected[:args].size, args.size]
+ unless x_call
+ raise MockExpectationError, "mocked method %p called with unexpected arguments %p" %
+ [sym, args]
end
+ expected_args, retval = x_call[:args], x_call[:retval]
+
@actual_calls[sym] << {
:retval => retval,
:args => expected_args.zip(args).map { |mod, a| mod === a ? mod : a }
View
@@ -78,9 +78,9 @@ def test_blow_up_on_wrong_arguments
@mock.meaning_of_life
@mock.expect(:sum, 3, [1, 2])
- @mock.sum(2, 4)
-
- util_verify_bad
+ assert_raises MockExpectationError do
+ @mock.sum(2, 4)
+ end
end
def test_expect_with_non_array_args
@@ -142,15 +142,19 @@ def test_verify_allows_called_args_to_be_loosely_specified
def test_verify_raises_with_strict_args
mock = MiniTest::Mock.new
mock.expect :strict_expectation, true, [2]
- mock.strict_expectation 1
- util_verify_bad
+ assert_raises MockExpectationError do
+ mock.strict_expectation 1
+ end
end
def test_verify_shows_the_actual_arguments_in_the_message
mock = MiniTest::Mock.new
mock.expect :capitalized, true, ["a"]
+ mock.expect :capitalized, true, ["b"]
+
mock.capitalized "b"
+
e = assert_raises MockExpectationError do
mock.verify
end
@@ -162,6 +166,27 @@ def test_verify_shows_the_actual_arguments_in_the_message
assert_equal expected, e.message
end
+ def test_same_method_expects_are_verified_when_all_called
+ mock = MiniTest::Mock.new
+ mock.expect :foo, nil, [:bar]
+ mock.expect :foo, nil, [:baz]
+
+ mock.foo :bar
+ mock.foo :baz
+
+ assert mock.verify
+ end
+
+ def test_same_method_expects_blow_up_when_not_all_called
+ mock = MiniTest::Mock.new
+ mock.expect :foo, nil, [:bar]
+ mock.expect :foo, nil, [:baz]
+
+ mock.foo :baz
+
+ assert_raises(MockExpectationError) { mock.verify }
+ end
+
def util_verify_bad
assert_raises MockExpectationError do
@mock.verify

0 comments on commit 88eec1b

Please sign in to comment.