I am attempting to use the class_double method explained here: https://relishapp.com/rspec/rspec-mocks/docs/verifying-doubles/using-a-class-double
Here is my code:
search.rb
class Search < ActiveRecord::Base
def find_events
events = Event.find_by_dates(beginning_date, end_date)
end
end
event.rb
class Event < ActiveRecord::Base
scope :find_by_dates, ->(starting_date , ending_date) { where('(date(start_datetime) >= ? AND date(end_datetime) <= ?)', starting_date.to_date, ending_date.to_date)}
end
search_spec.rb
let(:march1) {DateTime.parse('1st March 2014')}
let(:march3) {DateTime.parse('3rd March 2014')}
let(:march_search) {create(:search, beginning_date: march1, end_date: march3)}
let(:mar1_event) {create(:event,
start_datetime: DateTime.parse('1st March 2014 04:00:00 PM'),
end_datetime: DateTime.parse('1st March 2014 06:00:00 PM'))}
let(:mar2_event) {create(:event,
start_datetime: DateTime.parse('2nd March 2014 04:00:00 PM'),
end_datetime: DateTime.parse('2nd March 2014 06:00:00 PM'))}
let(:mar1_to_3_event) {create(:event,
start_datetime: DateTime.parse('1st March 2014 04:00:00 PM'),
end_datetime: DateTime.parse('3rd March 2014 06:00:00 PM'))}
let(:march_search) {create(:search, beginning_date: march1, end_date: march3)}
describe 'find_events method' do
it 'should call Event.find_by_dates' do
event = class_double("Event").as_stubbed_const(:transfer_nested_constants => true)
expect(event).to receive(:find_by_dates).with(march1, march3)
march_search.find_events
end
it 'should return events within a date range' do
events = march_search.find_events
expect(events).to include(mar1_event, mar2_event, mar1_to_3_event)
end
it 'it should not return events outside of the date range' do
events = sept_search.find_events
expect(events).to_not include(mar1_event, mar2_event, mar1_to_3_event)
end
So far no problem until I want to check if no results were found and return a string
def find_events
events = Event.find_by_dates(beginning_date, end_date)
if events.empty?
return "SORRY NO RESULTS FOUND"
end
end
Then I get the following errors
Failures:
1) Search find_events method it should not return events outside of the date range
Failure/Error: expect(events).to_not include(mar1_event, mar2_event, mar1_to_3_event)
TypeError:
no implicit conversion of Event into String
# ./spec/models/search_spec.rb:93:in `block (3 levels) in <top (required)>'
2) Search find_events method should call Event.find_by_dates
Failure/Error: march_search.find_events
NoMethodError:
undefined method `empty?' for nil:NilClass
# ./app/models/search.rb:41:in `find_events'
# ./spec/models/search_spec.rb:84:in `block (3 levels) in <top (required)>'
3) Search find_events method should return events within a date range
Failure/Error: expect(events).to include(mar1_event, mar2_event, mar1_to_3_event)
TypeError:
no implicit conversion of Event into String
# ./spec/models/search_spec.rb:88:in `block (3 levels) in <top (required)>'
I've the Event.find_by_dates to see if it was nil but received the following error: undefined method `include?' for nil:NilClass
I really need to check if an empty ActiveRelation object is returned to stop the search from continuing. Can anyone tell me how to test for empty and not empty search results?
Thanks!
Test is the wrong place. Test what is returned by Event.find_by_dates on the Event class.
All you care about for find_events in the Search class is whether it returns a collection of events or a string.
So you just stub find_by_dates on Event to return either something that is empty or not.
so you want the equivalent of Event.any_instance.stub(:find_by_dates).and_return('')
PS, don't forget to unstub it after the test. :(