How do you expect a message to be sent to any instance of a class (twice the size) with specific arguments in Rails?
When returning an order, we need to deactivate the serial files attached to this order. In the spec the order has two serials, ergo, I should expect two API calls that will take care of deactivating the serials.
I tried:
expect_any_instance_of(Gateway).to receive(:deactivate_dongle).once.with(serial_number: '67890')
expect_any_instance_of(Gateway).to receive(:deactivate_dongle).once.with(serial_number: '12345')
Which gives me:
The message 'deactivate_dongle' was received by #<Gateway:70179265658480 @connection=#<Faraday::Connection:0x007fa7c4667b28>> but has already been received by #<Gateway:0x007fa7c6858160>
The same for:
expect_any_instance_of(Gateway).to receive(:deactivate_dongle).with(serial_number: '12345')
expect_any_instance_of(Gateway).to receive(:deactivate_dongle).with(serial_number: '67890')
How can I achieve this?
source to share
If you can change your implementation to live up to the expectations of a known instance Gateway
(to avoid expect_any_instance_of
), you can use rspec ordered
to add restrictions on receiving messages.
I am afraid that in your case you should try to add a BOM where there is only one of these serials so you can expect it correctly. eg.
expect_any_instance_of(Gateway).to receive(:deactivate_dongle).once.with(serial_number: '67890')
And then you have a spec with n serials and just expect to deactivate_dongle
be called n times.
source to share
I think you want a Null Object :
Use the as_null_object method to ignore any messages that are not explicitly set as stubs or wait messages.
allow_any_instance_of(JarvisGateway).to receive(:deactivate_dongle).as_null_object
Here is another solution I was thinking about before I found the solution above. Blocks offer more flexibility in argument validation than built-in blocks. See Use a block to validate arguments .
allow_any_instance_of(JarvisGateway).to receive(:deactivate_dongle) do |args|
expect(['67890', '12345']).to include args[:serial_number]
end
expect_any_instance_of(JarvisGateway).to receive(:deactivate_dongle).twice
Not sure what allow_any_instance_of
supports blocks this way.
If it is not, you can do it by one or more of the following:
- Create an instance
JarvisGateway
and check the sent messages insteadallow_any_instance_of
. - Use
has_received
insteadto receive
. See Spies .
EDIT: expect_any_instance_of(JarvisGateway).to receive(:deactivate_dongle).twice
Not really that good because it doesn't check to make sure every serial number is called once.
source to share