Back to Repositories

Testing Global Initialize With Behavior in factory_bot

This test suite examines global initialize_with functionality in factory_bot, focusing on object initialization behavior across different factory definitions. It validates how initialize_with blocks are inherited and overridden in parent-child factory relationships and through traits.

Test Coverage Overview

The test suite provides comprehensive coverage of global initialize_with behavior in factory_bot.

Key areas tested include:
  • Base factory initialization with global initialize_with
  • Child factory inheritance of initialize_with blocks
  • Trait-based initialize_with overrides
  • Cross-factory global initialization consistency
  • Inline trait application effects

Implementation Analysis

The testing approach uses multiple factory definitions to verify initialization behavior across different contexts. It employs RSpec’s expect syntax with dynamic class definitions to test initialize_with functionality.

Key patterns include:
  • Dynamic class creation for test subjects
  • Nested factory definitions
  • Trait-based configuration
  • Global initialization block definition

Technical Details

Testing tools and setup:
  • RSpec testing framework
  • factory_bot for test data generation
  • Dynamic class definition helpers
  • Custom initialization blocks
  • Attribute accessor definitions

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Ruby and RSpec.

Notable practices include:
  • Isolated test scenarios
  • Clear test case organization
  • Comprehensive edge case coverage
  • DRY test definitions
  • Consistent assertion patterns

thoughtbot/factory_bot

spec/acceptance/global_initialize_with_spec.rb

            
describe "global initialize_with" do
  before do
    define_class("User") do
      attr_accessor :name

      def initialize(name)
        @name = name
      end
    end

    define_class("Post") do
      attr_reader :name

      def initialize(name)
        @name = name
      end
    end

    FactoryBot.define do
      initialize_with { new("initialize_with") }

      trait :with_initialize_with do
        initialize_with { new("trait initialize_with") }
      end

      factory :user do
        factory :child_user

        factory :child_user_with_trait do
          with_initialize_with
        end
      end

      factory :post do
        factory :child_post

        factory :child_post_with_trait do
          with_initialize_with
        end
      end
    end
  end

  it "handles base initialize_with" do
    expect(FactoryBot.build(:user).name).to eq "initialize_with"
    expect(FactoryBot.build(:post).name).to eq "initialize_with"
  end

  it "handles child initialize_with" do
    expect(FactoryBot.build(:child_user).name).to eq "initialize_with"
    expect(FactoryBot.build(:child_post).name).to eq "initialize_with"
  end

  it "handles child initialize_with with trait" do
    expect(FactoryBot.build(:child_user_with_trait).name).to eq "trait initialize_with"
    expect(FactoryBot.build(:child_post_with_trait).name).to eq "trait initialize_with"
  end

  it "handles inline trait override" do
    expect(FactoryBot.build(:child_user, :with_initialize_with).name).to eq "trait initialize_with"
    expect(FactoryBot.build(:child_post, :with_initialize_with).name).to eq "trait initialize_with"
  end

  it "uses initialize_with globally across FactoryBot.define" do
    define_class("Company") do
      attr_reader :name

      def initialize(name)
        @name = name
      end
    end

    FactoryBot.define do
      factory :company
    end

    expect(FactoryBot.build(:company).name).to eq "initialize_with"
    expect(FactoryBot.build(:company, :with_initialize_with).name).to eq "trait initialize_with"
  end
end