-
-
Save antillas21/11232600 to your computer and use it in GitHub Desktop.
# first we create an empty ActiveRecord::Relation object | |
relation = Model.where(attribute: value) | |
# then we make the relation stub the :[] method | |
# and return whatever values we need | |
relation.stub(:[]).and_return( Model.new({attrs: values})] ) | |
# of course, we can make this too | |
# instead of the step above | |
record = double("Model", :foo => 'bar', :bar => 'baz') | |
relation.stub(:[]).and_return([record]) | |
# last, we make our Model class stub the :where method | |
# and return the relation object we created | |
Model.stub(:where).and_return(relation) | |
# additionally we can have use case specific behavior | |
model_instance.stub(:method_or_scope_that_returns_collection) { relation } |
updated syntax like:
mocks = [fake_instance_1, fake_instance_2]
mock_relation = Model.where(id: 1)
allow(mock_relation).to receive(:[]).and_return(mocks)
allow(mock_relation).to receive(:where).and_return(mock_relation)
This simply doesn't work - accessing relation[0]
will return an array of records, rather than a single record. Furthermore, .any?
, .first
, .last
, etc. are completely nonfunctional.
The correct way to do this is
mocked_relation = Model.all
mocked_relation.stub(:records).and_return(my_custom_array_of_records)
allow(my_instance).to receive(:my_method).and_return(mocked_relation)
Furthermore you can mock a has_many
relation (which was my use case) by doing
allow(record).to receive(:related_records).and_wrap_original do |original, *args, &block|
relation = original.call(*args, &block)
relation.stub(:records).and_return(my_custom_array_of_related_records)
relation
end
Furthermore you can mock a
has_many
relation (which was my use case) by doingallow(record).to receive(:related_records).and_wrap_original do |original, *args, &block| relation = original.call(*args, &block) relation.stub(:records).and_return(my_custom_array_of_related_records) relation end
I wonder why your code didn't work in my particular case. Could it be related to my call of relation = original.call(*args, &block)
always returning a nil
object?
relation.stub(:records)
raises unknown #stub method for #<ActiveRecord::Associations::CollectionProxy []>
But I found a way out of this, not sure if ideal, though:
allow(record).to receive(:related_records).and_wrap_original do |original, *args, &block|
relation = original.call(*args, &block)
relation << custom_records
allow(relation).to receive(:scope_of_related_class).and_return(scoped_custom_records)
relation
end
Mocking only the has_many
return was insufficient for my case because I also needed to mock the scope call.
record.related_records.scope_of_related_class
Thanks!
Line 6 is missing a square brace.