Question: How to test receipt of the same method with different arguments on different instances

Question

How to test receipt of the same method with different arguments on different instances

Answers 1
Added at 2017-07-20 09:07
Tags
Question

I have my method like

def my_method
  MyClass.new.track(arg1, arg2)

  if satisfies_some_condition
    2.times { MyClass.new.track(arg3, arg4) }
  end
end

In RSpec, I want to test receipt of #track

expect_any_instance_of(MyClass).to receive(:track).with(arg1, arg2)
expect_any_instance_of(MyClass).to receive(:track).with(arg3, arg4).twice

But I am getting this error

The message 'track' was received by #<MyClass:70362069595680 > but has already been received by #<MyClass:0x007ffce788e460>

It seems here it's suggested that it should be resolved by upgrading to RSpec-mocks v3.6.0 But I am still getting the same error even after upgrading my RSpec-mocks gem to v3.6.0

Answers to

How to test receipt of the same method with different arguments on different instances

nr: #1 dodano: 2017-07-20 10:07

I've never liked any_instance so not sure how to do what you're wanting with it, however, an alternative that may do what you're wanting just as well is something like

class MyClass
  def track(a, b)
  end
end

def my_method(pass = true)
  MyClass.new.track('a', 'b')

  if pass
    2.times { MyClass.new.track('c', 'd') }
  end
end

RSpec.describe "SO question" do
  it 'pass' do
    first = double(MyClass)
    expect(first).to receive(:track).with('a', 'b')
    second = double(MyClass)
    expect(second).to receive(:track).with('c', 'd').twice

    allow(MyClass).to receive(:new).and_return(first, second)
    my_method
  end

  it 'fail' do
    first = double(MyClass)
    expect(first).to receive(:track).with('a', 'b')
    second = double(MyClass)
    expect(second).to receive(:track).with('c', 'd').twice

    allow(MyClass).to receive(:new).and_return(first, second)
    my_method(false)
  end
end

Bit more verbose, but forces the new method to return multiple instances that have expectations on them. and_return will return those values in order each time it's called and then will just keep returning the last value for any additional calls.

Source Show
◀ Wstecz