Question

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!

Was it helpful?

Solution

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. :(

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top