diff --git a/lib/flexmock/argument_matchers.rb b/lib/flexmock/argument_matchers.rb index 9bf76d8..dbbb70f 100644 --- a/lib/flexmock/argument_matchers.rb +++ b/lib/flexmock/argument_matchers.rb @@ -75,12 +75,28 @@ def initialize(expected) end def ===(target) return false unless target.kind_of?(Hash) - return false unless @expected.all? { |k, v| v === target[k] } + matching = @expected.all? do |k, v| + v === target[k] || v == target[k] + end + return false unless matching @expected.size == target.size end def inspect - "kw(#{@expected.inspect})" + args = @expected.map do |k, v| + k_s = case k + when Symbol + "#{k}: " + else + "#{k.inspect} => " + end + + v_s = FlexMock.forbid_mocking("") do + v.inspect + end + "#{k_s}#{v_s}" + end + args.join(", ") end end diff --git a/lib/flexmock/core_class_methods.rb b/lib/flexmock/core_class_methods.rb index 67d7b54..5f9bb80 100644 --- a/lib/flexmock/core_class_methods.rb +++ b/lib/flexmock/core_class_methods.rb @@ -97,6 +97,18 @@ def format_args(args) end end + # Class method to format a list of args (the part between the + # parenthesis). + def format_kw_args(args) + if args + FlexMock.forbid_mocking("") do + args.inspect + end + else + "**args" + end + end + # Check will assert the block returns true. If it doesn't, an # assertion failure is triggered with the given message. def check(msg, &block) # :nodoc: diff --git a/lib/flexmock/expectation.rb b/lib/flexmock/expectation.rb index 1b514d1..25add14 100644 --- a/lib/flexmock/expectation.rb +++ b/lib/flexmock/expectation.rb @@ -65,6 +65,7 @@ def to_s def description result = ["should_receive(#{@sym.inspect})"] result << ".with(#{FlexMock.format_args(@expected_args)})" if @expected_args + result << ".with_kw_args(#{FlexMock.format_kw_args(@expected_kw_args)})" if @expected_kw_args @count_validators.each do |validator| result << validator.describe end diff --git a/test/expectation_description_test.rb b/test/expectation_description_test.rb index 2e323b6..73704be 100644 --- a/test/expectation_description_test.rb +++ b/test/expectation_description_test.rb @@ -78,6 +78,15 @@ def test_with_at_least_1_at_most_10 assert_equal "should_receive(:foo).at_least.once.at_most.times(10)", @exp.description end + def test_with_kw_args + @exp.at_least.once.with_kw_args(a: 10, "b" => 20) + + description = <<~EOD + should_receive(:foo).with_kw_args(a: 10, "b" => 20).at_least.once + EOD + assert_equal description.chomp, @exp.description + end + def test_with_signature @exp.at_least.once.with_signature(required_arguments: 2, optional_arguments: 3, required_keyword_arguments: [:test], diff --git a/test/should_receive_test.rb b/test/should_receive_test.rb index 54fa51d..15d414c 100644 --- a/test/should_receive_test.rb +++ b/test/should_receive_test.rb @@ -439,13 +439,36 @@ def test_with_hash_non_matching end end - def test_with_kw_args_matching + def test_with_kw_args_matching_equality FlexMock.use('greeter') do |m| m.should_receive(:hi).with_kw_args(some: 10) m.hi(some: 10) end end + def test_with_kw_args_matching_with_case_operator + FlexMock.use('greeter') do |m| + m.should_receive(:hi).with_kw_args(some: 9..11) + m.hi(some: 10) + end + end + + def test_with_kw_args_matching_with_equality_operator + FlexMock.use('greeter') do |m| + m.should_receive(:hi).with_kw_args(some: 9..11) + m.hi(some: 9..11) + end + end + + def test_with_kw_args_matching_strictly_with_equality_with_the_eq_operator + assert_raises(FlexMock::CheckFailedError) do + FlexMock.use('greeter') do |m| + m.should_receive(:hi).with_kw_args(some: eq(9..11)) + m.hi(some: 10) + end + end + end + def test_with_kw_args_matches_values_separately FlexMock.use('greeter') do |m| m.should_receive(:hi).with_kw_args(a: on { |v| v == 1 }, b: 2).once