Hello!

Its likely that you are confusing Rails here, it generally doesn't (pardon the 
pun) expect models to be dynamically created and thus may well be keeping 
things around.

I can suggest two alternative strategies, one is set up a temporary set of 
models for the entire test run that don't change, another is to generate a new 
rails app each time you need to and shell out to it, we do something similar 
within rspec-rails to smoke test various integrations.

I can confirm that your constants would be cleared up, but theres no magic 
within RSpec to ensure there are no references to those classes other than 
their constants, thats a bit beyond our reach.

Cheers
Jon

On Tue, 27 Jul 2021, at 3:56 PM, Joseph Haig wrote:
> I am attempting to refactor the tests in the amoeba gem 
> (https://github.com/amoeba-rb/amoeba) with a view to being able to fix some 
> bugs and (possibly) add new features.
> 
> The tests require ActiveRecord models with associations (has_one, has_many, 
> etc) and for the existing tests these are defined all together in one place 
> for the whole suite but, for me, this makes it hard to understand what 
> features are tested in each unit test. I would therefore like to create 
> temporary models with each test, and I can do that as follows:
> 
> ```
> # Create the tables in the database
> ActiveRecord::Base.connection.drop_table :parents, if_exists: true
> ActiveRecord::Base.connection.drop_table :children, if_exists: true
> ActiveRecord::Base.connection.create_table :parents
> ActiveRecord::Base.connection.create_table :children do |t|
>   t.references :parent
> end
> 
> # Stub models (so that they are discarded after the tests)
> stub_const 'Parent', Class.new(ActiveRecord::Base)
> stub_const 'Child', Class.new(ActiveRecord::Base)
> 
> # Configure the models, as required
> Parent.class_eval 'has_one :child'
> ```
> 
> This works OK but I have a problem if I try to use the same temporary model 
> names with a different association type. Here is an example:
> 
> ```
> require 'spec_helper'
> 
> RSpec.describe 'testing' do
>   before do
>     ActiveRecord::Base.connection.drop_table :parents, if_exists: true
>     ActiveRecord::Base.connection.drop_table :children, if_exists: true
>     ActiveRecord::Base.connection.create_table :parents
>     ActiveRecord::Base.connection.create_table :children do |t|
>       t.references :parent
>     end
> 
>     stub_const 'Parent', Class.new(ActiveRecord::Base)
>     stub_const 'Child', Class.new(ActiveRecord::Base)
>   end
> 
>   describe 'has_one' do
>     subject(:record) { Parent.create(child: Child.new) }
> 
>     before do
>       Parent.class_eval 'has_one :child, inverse_of: :parent'
>       Child.class_eval 'belongs_to :parent, inverse_of: :child'
>     end
> 
>     it { expect { record }.not_to raise_error }
>   end
> 
>   describe 'has_many' do
>     subject(:record) { Parent.create(children: [Child.new]) }
> 
>     before do
>       Parent.class_eval 'has_many :children, inverse_of: :parent'
>       Child.class_eval 'belongs_to :parent, inverse_of: :children'
>     end
> 
>     it { expect { record }.not_to raise_error }
>   end
> end
> ```
> 
> The Parent model in the first case has a 'has_one' association and in the 
> second case there is a 'has_many' association. The test in each case checks 
> that an instance can be created. When running each individually (`rspec 
> spec/test_spec.rb:24` and `rspec spec/test_spec.rb:35`) they both pass but 
> when run together I get:
> 
> expected no Exception, got #<ActiveRecord::InverseOfAssociationNotFoundError: 
> Could not find the inverse association for parent (:children in Parent)> with 
> backtrace:
> 
> with the second test. This suggests to me that the tests are not correctly 
> isolated, and the configuration of the first is affecting the second. I had 
> hoped that the stubbed constants for the models would ensure that all 
> configuration is discarded but is there some sort of cache in ActiveRecord 
> that needs to be cleared? Or maybe what I'm doing is crazy?
> 
> Thanks,
> 
> Joe
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "rspec" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to rspec+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/rspec/CAKRXwc0J5pTcJnb-01tE8Nq8iS9e8y4grOMqf_vabidC2w-tDw%40mail.gmail.com
>  
> <https://groups.google.com/d/msgid/rspec/CAKRXwc0J5pTcJnb-01tE8Nq8iS9e8y4grOMqf_vabidC2w-tDw%40mail.gmail.com?utm_medium=email&utm_source=footer>.

-- 
You received this message because you are subscribed to the Google Groups 
"rspec" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to rspec+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/rspec/4987bfb8-eca4-485b-a845-cfdbf095f08b%40www.fastmail.com.

Reply via email to