Currently if you have a method that is called multiple times and you want to ensure that a certain call occurred then you need to write a lot of dummy code.
events = []
Analytics.should_receive(:track) do |event|
events << event
end.any_number_of_times
<<INVOKE CONTROLLER ACTION>>
event = events.find{|event| event.event_name == 'MyEventName'}
event.should_not be_nil
event.properties.should include({ property_a: value})
The above code is needed to 1. Record all the events that were tracked 2. Find at least one instance of a certain event name and match the properties
This results in a lot of lines of code when there should be a simpler way.
Analytics.should_receive(:track) do |event|
expect(event.event_name).to eq('MyEventName')
expect(event.properties).to include({ property_a: value})
end.at_least(:once)
Unfortunately the above will only work if the very first call to Analytics.track results in a match. If it was the second call this test will fail.
I have my own solution to try and make it generic and reusable but I would like to know if there is a simple way to accomplish this already that I may be missing.
You can try passing the exact event that you expect to with
. The key here is stubbing track
prior to calling should_receive
.
Here's an example code:
require 'ostruct'
class Analytics
def self.run
track(OpenStruct.new(event_name: 'test1', properties: { a: '1' }))
track(OpenStruct.new(event_name: 'test2', properties: { a: '2' }))
end
def self.track(event)
end
end
describe Analytics do
it 'verifies the second event' do
expected_event = OpenStruct.new(event_name: 'test2', properties: { a: '2' })
Analytics.stub(:track)
Analytics.should_receive(:track).with(expected_event)
Analytics.run
end
end