-
-
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
endFurthermore you can mock a
has_manyrelation (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
endMocking 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.