rspec-mocks icon indicating copy to clipboard operation
rspec-mocks copied to clipboard

Expect to have_received(method).with({}) fails when method modifies the Hash

Open bvrooman opened this issue 6 years ago • 9 comments

What Ruby, Rails and RSpec versions are you using?

Ruby version: ruby 2.3.7p456 (2018-03-28 revision 63024) [x86_64-darwin17] Rails version: Rails 5.2.1 Rspec version: RSpec 3.8

Observed behaviour

I am using Rspec to test the presence of a method call with the correct parameters. I invoke the method call with

my_callable.call({})

and I test the call using

expect(my_callable).to have_received(:call).with({})

When call modifies the provided hash argument, like context[:value] = true, this test fails, when it should succeed. This produces the output:

#<MyCallable:0x00007f9505aa5518> received :call with unexpected arguments
  expected: ({})
       got: ({:value=>true})
Diff:
@@ -1,2 +1,2 @@
-[{}]
+[{:value=>true}]

It appears that the expect call is referencing the hash modified in memory, rather than a saved copy of the hash when the call was actually made.

Expected behaviour

I expect this test to pass. Because the call to the method call was made with an empty hash {}, the expect statement

expect(my_callable).to have_received(:call).with({})

is correct.

Can you provide an example app?

Link to repo: https://github.com/bvrooman/Rspec-Issue-2044

I found that this contrived code can reproduce the issue:

Inside any _spec file:

class MyCallable
  def call(context)
    context[:value] = true
  end
end

let(:my_callable) { MyCallable.new }

describe 'MyCallable #call' do
  it 'is called with the right arguments' do
    allow(my_callable).to receive(:call).and_call_original
    my_callable.call({})
    expect(my_callable).to have_received(:call).with({})
  end
end

This results in the following failure:

#<MyCallable:0x00007f9505aa5518> received :call with unexpected arguments
  expected: ({})
       got: ({:value=>true})
Diff:
@@ -1,2 +1,2 @@
-[{}]
+[{:value=>true}]

bvrooman avatar Nov 28 '18 20:11 bvrooman