According to the rspec expect message docs, when we use code like:
expect(double).to receive(:message).with(argument)
and argument
responds to #===
, Rspec will call argument.===
on whatever is actually passed in. But what should I do if I want to check that a range of times is actually passed in?
For example, I wanted to test that this method sends the right message with the correct arguments (it's simplified):
def in_date_range(range)
activities.by_created_at(range)
end
And a test like:
it 'passes correct arguments' do
range = Time.new(0)..(Time.new(0) + 1.hour)
expect(activities).to receive(:by_created_at).with(range)
in_date_range(range)
end
This fails with TypeError: can't iterate from Time
I am suspecting it's because which rspec tries to call #===
on my time range and runs into trouble.
Is there a way to check that my range of times is actually the range I pass in?
I'm not actually looking for the times to overlap, but rather that the ranges are the same: That have the same start and end points.
I suppose one way we can do this is to write a custom matcher, but it seems an unusual route.
EDIT
Another possible solution is to split the method into two pieces:
def compute_range(time_in)
(computations)
time1..time2
end
def in_date_range(time_in)
range = compute_range(time_in)
activities.by_created_at(range)
end
Then I can test compute method that it returns the proper range, and the for the larger method I can test that passes in the correct input, and takes the output of the smaller method it takes the result from the first and passes into the other method, sidestepping the confusion of checking ranges in message.
This doesn't fully answer the question - how do you check 'receive a specific range' with the rspec receive(:message), but is enough for me right now.