Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Eloquent Testsuite Laravel Package

sofa/eloquent-testsuite

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require --dev sofa/eloquent-testsuite
    

    Add the trait to your test class:

    use Sofa\EloquentTestsuite\EloquentSuite;
    
  2. First Use Case: Test a simple belongsTo relation:

    class UserTest extends TestCase
    {
        use EloquentSuite;
    
        /** @test */
        public function user_has_post()
        {
            $user = $this->createRelationMock(User::class, 'belongsTo', Post::class);
            $this->assertRelation('belongsTo', $user->post());
        }
    }
    
  3. Key Files to Explore:

    • tests/Feature/Models/ – Your model tests.
    • src/Sofa/EloquentTestsuite/EloquentSuite.php – Core trait methods.

Implementation Patterns

Common Workflows

1. Testing Basic Relations

// Mock a belongsTo relation
$user = $this->createRelationMock(User::class, 'belongsTo', Post::class);
$this->assertRelation('belongsTo', $user->post());

// Mock a hasMany relation with query constraints
[$user, $relation] = $this->createRelationChainMock(User::class, 'hasMany', Post::class);
$relation->shouldReceive('whereActive')->once()->andReturnSelf();
$this->assertRelation('hasMany', $user->posts());

2. Testing Scopes

// Assert a scope exists and filters correctly
$this->assertScopeFilters(User::class, 'active', 'is_active', true);
$this->assertScopeFilters(User::class, 'archived', 'is_active', false);

// Test scope chaining
$this->assertScopeFilters(User::class, 'activeArchived', 'is_active', true)
      ->assertScopeFilters(User::class, 'activeArchived', 'archived', true);

3. Testing Model Events

// Mock event listeners
$user = $this->createModelMock(User::class);
$user->shouldReceive('fireModelEvent')->with('creating')->once();
$this->createModel(User::class);

4. Testing Custom Accessors/Mutators

$user = $this->createModelMock(User::class);
$user->shouldReceive('getFullNameAttribute')->once()->andReturn('John Doe');
$this->assertAttribute('full_name', 'John Doe', $user);

5. Integration with Factories

// Combine with Laravel factories for realistic data
$user = User::factory()->create();
$this->assertDatabaseHas('users', ['id' => $user->id]);

Integration Tips

Mocking Complex Relations

Use createRelationChainMock for nested relations:

[$user, $posts, $comments] = $this->createRelationChainMock(
    User::class,
    'hasMany',
    Post::class,
    'hasMany',
    Comment::class
);

Testing Polymorphic Relations

$this->createRelationMock(
    User::class,
    'morphTo',
    [Post::class, Comment::class]
);

Asserting Query Constraints

$this->assertQueryConstraints(
    User::where('active', true)->get(),
    ['active' => true]
);

Testing Model Casting

$user = $this->createModelMock(User::class);
$user->shouldReceive('getAttributeFromArray')->with('email')->andReturn('test@example.com');
$this->assertAttribute('email', 'test@example.com', $user);

Gotchas and Tips

Pitfalls

  1. Mocking Static Methods: The package doesn’t natively support static methods (e.g., Model::boot()). Use Mockery directly:

    $mock = Mockery::mock(User::class . '::class');
    $mock->shouldReceive('boot')->once();
    
  2. Database Transactions: Ensure tests run in a transaction to avoid side effects:

    public function setUp(): void
    {
        parent::setUp();
        $this->beginDatabaseTransaction();
    }
    
  3. Time-Sensitive Scopes: Mock Carbon or now() in scopes:

    $mock = Mockery::mock('overload:' . Carbon::class);
    $mock->shouldReceive('now')->andReturn(Carbon::create(2023, 1, 1));
    
  4. Laravel 8+ Compatibility: The package was last updated in 2020. For Laravel 8/9, manually patch:

    // In phpunit.xml
    <php>
        <env name="DB_CONNECTION" value="sqlite_memory"/>
    </php>
    

Debugging Tips

  1. Inspect Mocks: Use dd($this->createRelationMock(...)) to verify mock setup.

  2. Assertion Failures: Enable detailed error output:

    $this->assertRelation('belongsTo', $user->post(), true); // Verbose mode
    
  3. Scope Testing: If assertScopeFilters fails, manually verify the query:

    $query = User::active()->toSql();
    $this->assertStringContainsString('is_active = 1', $query);
    

Extension Points

  1. Custom Assertions: Extend the trait to add domain-specific assertions:

    trait CustomAssertions
    {
        protected function assertCustomValidation($model, $rules)
        {
            // Custom logic
        }
    }
    
  2. Mocking Observers: Use Mockery to stub observer methods:

    $observer = Mockery::mock(UserObserver::class);
    $observer->shouldReceive('saved')->once();
    
  3. Testing API Resources: Combine with Laravel\Sanctum or Laravel\Passport mocks:

    $user = $this->createModelMock(User::class);
    $user->shouldReceive('toArray')->andReturn(['id' => 1]);
    
  4. Performance Testing: Use Benchmark trait for timing:

    use Sofa\EloquentTestsuite\Benchmark;
    $this->benchmark('Model hydration', function () {
        User::find(1);
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui