Back to Repositories

Testing Implicit Declaration Handling in factory_bot

This test suite examines the implicit declaration functionality in FactoryBot, focusing on association and sequence handling. The tests verify the behavior of implicit declarations for both known factories and sequences, along with comprehensive equality comparison scenarios.

Test Coverage Overview

The test suite provides comprehensive coverage of FactoryBot’s Declaration::Implicit class functionality.

Key areas tested include:
  • Association attribute creation for known factories
  • Factory name validation
  • Sequence attribute handling
  • Equality comparison across different scenarios

Implementation Analysis

The testing approach uses RSpec’s context-based organization to systematically verify different aspects of implicit declarations. The implementation leverages mocking with allow/receive patterns to isolate factory and sequence registration checks.

Technical patterns include:
  • Stub-based dependency isolation
  • Attribute type verification
  • Equality comparison matrices

Technical Details

Testing tools and configuration:
  • RSpec as the testing framework
  • FactoryBot’s internal testing utilities
  • Mock objects for factory and sequence registration
  • Attribute type checking mechanisms

Best Practices Demonstrated

The test suite exemplifies several testing best practices including clear context separation, comprehensive edge case coverage, and thorough equality testing.

Notable practices:
  • Structured context organization
  • Isolated test scenarios
  • Comprehensive equality comparison cases
  • Clear test descriptions

thoughtbot/factory_bot

spec/factory_bot/declaration/implicit_spec.rb

            
describe FactoryBot::Declaration::Implicit do
  context "with a known factory" do
    it "creates an association attribute" do
      allow(FactoryBot.factories).to receive(:registered?).and_return true

      declaration = FactoryBot::Declaration::Implicit.new(:name)
      attribute = declaration.to_attributes.first

      expect(attribute).to be_association
    end

    it "has the correct factory name" do
      allow(FactoryBot.factories).to receive(:registered?).and_return true
      name = :factory_name

      declaration = FactoryBot::Declaration::Implicit.new(name)
      attribute = declaration.to_attributes.first

      expect(attribute.factory).to eq(name)
    end
  end

  context "with a known sequence" do
    it "does not create an association attribute" do
      allow(FactoryBot::Internal.sequences).to receive(:registered?).and_return true

      declaration = FactoryBot::Declaration::Implicit.new(:name)
      attribute = declaration.to_attributes.first

      expect(attribute).not_to be_association
    end

    it "creates a sequence attribute" do
      allow(FactoryBot::Internal.sequences).to receive(:registered?).and_return true

      declaration = FactoryBot::Declaration::Implicit.new(:name)
      attribute = declaration.to_attributes.first

      expect(attribute).to be_a(FactoryBot::Attribute::Sequence)
    end
  end

  describe "#==" do
    context "when the attributes are equal" do
      it "the objects are equal" do
        declaration = described_class.new(:name, :factory, false)
        other_declaration = described_class.new(:name, :factory, false)

        expect(declaration).to eq(other_declaration)
      end
    end

    context "when the names are different" do
      it "the objects are NOT equal" do
        declaration = described_class.new(:name, :factory, false)
        other_declaration = described_class.new(:other_name, :factory, false)

        expect(declaration).not_to eq(other_declaration)
      end
    end

    context "when the factories are different" do
      it "the objects are NOT equal" do
        declaration = described_class.new(:name, :factory, false)
        other_declaration = described_class.new(:name, :other_factory, false)

        expect(declaration).not_to eq(other_declaration)
      end
    end

    context "when one is ignored and the other isn't" do
      it "the objects are NOT equal" do
        declaration = described_class.new(:name, :factory, false)
        other_declaration = described_class.new(:name, :factory, true)

        expect(declaration).not_to eq(other_declaration)
      end
    end

    context "when comparing against another type of object" do
      it "the objects are NOT equal" do
        declaration = described_class.new(:name, :factory, false)

        expect(declaration).not_to eq(:not_a_declaration)
      end
    end
  end
end