diff --git a/lib/minitest/mock.rb b/lib/minitest/mock.rb index 41e28cb9..16f81505 100644 --- a/lib/minitest/mock.rb +++ b/lib/minitest/mock.rb @@ -30,9 +30,17 @@ class Mock overridden_methods.map(&:to_sym).each do |method_id| define_method method_id do |*args, **kwargs, &b| if @expected_calls.key? method_id then - method_missing(method_id, *args, **kwargs, &b) + if kwargs.empty? then # FIX: drop this after 2.7 dead + method_missing(method_id, *args, &b) + else + method_missing(method_id, *args, **kwargs, &b) + end else - super(*args, **kwargs, &b) + if kwargs.empty? then # FIX: drop this after 2.7 dead + super(*args, &b) + else + super(*args, **kwargs, &b) + end end end end @@ -242,30 +250,38 @@ class Object # NOTE: keyword args in callables are NOT checked for correctness # against the existing method. Too many edge cases to be worth it. - def stub name, val_or_callable, *block_args + def stub name, val_or_callable, *block_args, **block_kwargs new_name = "__minitest_stub__#{name}" metaclass = class << self; self; end if respond_to? name and not methods.map(&:to_s).include? name.to_s then - metaclass.send :define_method, name do |*args| - super(*args) + metaclass.send :define_method, name do |*args, **kwargs| + super(*args, **kwargs) end end metaclass.send :alias_method, new_name, name - metaclass.send :define_method, name do |*args, &blk| + metaclass.send :define_method, name do |*args, **kwargs, &blk| if val_or_callable.respond_to? :call then - val_or_callable.call(*args, &blk) + if kwargs.empty? then # FIX: drop this after 2.7 dead + val_or_callable.call(*args, &blk) + else + val_or_callable.call(*args, **kwargs, &blk) + end else - blk.call(*block_args) if blk + if blk then + if block_kwargs.empty? then # FIX: drop this after 2.7 dead + blk.call(*block_args) + else + blk.call(*block_args, **block_kwargs) + end + end val_or_callable end end - metaclass.send(:ruby2_keywords, name) if metaclass.respond_to?(:ruby2_keywords, true) - yield self ensure metaclass.send :undef_method, name diff --git a/test/minitest/test_minitest_mock.rb b/test/minitest/test_minitest_mock.rb index 23ec8cff..c50179f0 100644 --- a/test/minitest/test_minitest_mock.rb +++ b/test/minitest/test_minitest_mock.rb @@ -319,7 +319,8 @@ def test_mock_block_is_passed_keyword_args__block_bad_missing mock.foo(k1: arg1, k2: arg2) end - assert_equal "missing keyword: :k3", e.message # basically testing ruby + # basically testing ruby ... need ? for ruby < 2.7 :( + assert_match(/missing keyword: :?k3/, e.message) end def test_mock_block_is_passed_keyword_args__block_bad_extra @@ -333,7 +334,8 @@ def test_mock_block_is_passed_keyword_args__block_bad_extra mock.foo(k1: arg1, k2: arg2, k3: arg3) end - assert_equal "unknown keyword: :k3", e.message # basically testing ruby + # basically testing ruby ... need ? for ruby < 2.7 :( + assert_match(/unknown keyword: :?k3/, e.message) end def test_mock_block_is_passed_keyword_args__block_bad_value @@ -661,6 +663,19 @@ def test_mock_with_yield @tc.assert_equal true, rs end + def test_mock_with_yield_kwargs + mock = Minitest::Mock.new + rs = nil + + File.stub :open, true, mock, kw:42 do + File.open "foo.txt", "r" do |f, kw:| + rs = kw + end + end + + @tc.assert_equal 42, rs + end + alias test_stub_value__old test_stub_value # TODO: remove/rename ## Permutation Sets: