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.