PHPackages                             tkaratug/eloquent-scope-assertion - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Testing &amp; Quality](/categories/testing)
4. /
5. tkaratug/eloquent-scope-assertion

ActiveLibrary[Testing &amp; Quality](/categories/testing)

tkaratug/eloquent-scope-assertion
=================================

Eloquent scope assertion for testing Laravel applications.

1.2.0(3y ago)183451MITPHPPHP ^8.0|^8.1|^8.2

Since Apr 24Pushed 3y ago1 watchersCompare

[ Source](https://github.com/tkaratug/eloquent-scope-assertion)[ Packagist](https://packagist.org/packages/tkaratug/eloquent-scope-assertion)[ Docs](https://github.com/tkaratug/eloquent-scope-assertion)[ RSS](/packages/tkaratug-eloquent-scope-assertion/feed)WikiDiscussions main Synced 4w ago

READMEChangelog (4)Dependencies (1)Versions (6)Used By (0)

Eloquent Scope Assertion
========================

[](#eloquent-scope-assertion)

[![Latest Version on Packagist](https://camo.githubusercontent.com/6aca25ae37a54294ed5fe2bb44fcdb26920bb8634b97cc54fca4a0e87b3b828a/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f746b6172617475672f656c6f7175656e742d73636f70652d617373657274696f6e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/tkaratug/eloquent-scope-assertion)[![Total Downloads](https://camo.githubusercontent.com/c33073b6f27c56b0160a9bbb618216eae44d893ac245ed9a824762f52a55d98b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f746b6172617475672f656c6f7175656e742d73636f70652d617373657274696f6e2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/tkaratug/eloquent-scope-assertion)

This package allows you to assert that the scope of a model is called in your tests.

Installation
------------

[](#installation)

You can install the package via composer:

```
composer require tkaratug/eloquent-scope-assertion
```

Use Case
--------

[](#use-case)

Let's say you have a complicated conditional query for Orders that is imported to be tested.

- Get the orders that have not been paid.
- Sorted by creation date descending.
- The list could go on.

The above query constraints should be tested at the feature level, so that you have tests like so;

- `user_can_get_orders`
- `user_can_get_only_unpaid_orders`
- `user_can_get_orders_by_created_at_desc`
- The list could go on.

Since the query is happening in the model scope it would be nice to test the query in the model's unit test and therefore only write the test coverage once.

However, in your feature tests, it's hard to be sure that the model scope with test coverage is actually used in your controller, so you'll likely duplicate that test coverage in your Feature tests in some way. Thus, you make the unit test you write quite meaningless.

As a solution of that, this package triggers an event that contains the name of the scope and model when a model scope is called. In this way, it is quite easy to assert that the event is dispatched with the correct scope and model names in feature tests.

Usage
-----

[](#usage)

Add the `HasScopeAssertion` trait to the `TestCase` class in order to be able to call `assertScopeCalled()` method in your feature tests.

Since the `ModelScopeCalled` event is triggered when a named scope is called, you should fake it in `setUp()` method.

```
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Tkaratug\EloquentScopeAssertion\Traits\HasScopeAssertion;
use Illuminate\Support\Facades\Event;
use App\Events\ModelScopeCalled;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
    use HasScopeAssertion;

    public function setUp(): void
    {
        parent::setUp();

        Event::fake([ModelScopeCalled::class]);
    }
}
```

Then add the `HasScopeWatcher` trait in your models to be able to assert its scopes.

```
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Tkaratug\EloquentScopeAssertion\Traits\HasScopeWatcher;

class Order extends Model
{
    use HasFactory;
    use HasScopeWatcher;

    public function scopeUnpaid(Builder $query): Builder
    {
        return $query->where('is_paid', false);
    }

    public function scopeCreatedAtDesc(Builder $query): Builder
    {
        return $query->latest('created_at');
    }
}
```

Let's say you want to see only unpaid orders sorted by creation date descending.

The `OrderController` should be like this;

```
use App\Models\Order;
use App\Http\Resources\OrderResource;

public OrderController extends Controller
{
    public function index(): void
    {
        $orders = Order::query()
                       ->unpaid()
                       ->createdAtDesc()
                       ->get();

        return OrderResource::collection($orders);
    }
}
```

Now you can simplify your test coverage in `OrderControllerTest` like so;

```
use App\Models\Order;
use Illuminate\Database\Eloquent\Factories\Sequence;

class OrderControllerTest extends TestCase
{
    public function user_can_get_unpaid_orders_sorted_by_creation_date_descenting(): void
    {
        Order::factory()
             ->unpaid()
             ->createMany([
                 ['created_at' => Carbon::parse('7 days ago')],
                 ['created_at' => Carbon::parse('14 days ago')],
                 ['created_at' => Carbon::parse('21 days ago')],
             ]);

        $response = $this->get(route('orders.index'));

        $response->assertOk();

        $this->assertScopeCalled('unpaid', Order::class);
        $this->assertScopeCalled('createdAtDesc', Order::class);
    }
}
```

If you want to assert how many times a query scope is called, just add a number as third parameter to `assertScopeCalled()` method.

```
// The `unpaid` scope must have been called 2 times in tested code.
$this->assertScopeCalled('unpaid', Order::class, 2);
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security
--------

[](#security)

If you discover any security related issues, please email  instead of using the issue tracker.

Credits
-------

[](#credits)

- [Turan Karatug](https://github.com/tkaratug)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

31

—

LowBetter than 68% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity64

Established project with proven stability

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~100 days

Total

4

Last Release

1175d ago

PHP version history (2 changes)1.0.0PHP ^8.0|^8.1

1.2.0PHP ^8.0|^8.1|^8.2

### Community

Maintainers

![](https://www.gravatar.com/avatar/50dc98a0c75a1aaba61d52bb073e1b0cbdb17f4d5ed4bd1c694c71784b088e16?d=identicon)[tkaratug](/maintainers/tkaratug)

---

Top Contributors

[![tkaratug](https://avatars.githubusercontent.com/u/4394344?v=4)](https://github.com/tkaratug "tkaratug (12 commits)")

---

Tags

testlaraveleloquentassertionscope

### Embed Badge

![Health badge](/badges/tkaratug-eloquent-scope-assertion/health.svg)

```
[![Health](https://phpackages.com/badges/tkaratug-eloquent-scope-assertion/health.svg)](https://phpackages.com/packages/tkaratug-eloquent-scope-assertion)
```

###  Alternatives

[zenstruck/assert

Standalone, lightweight, framework agnostic, test assertion library.

8114.9M8](/packages/zenstruck-assert)[fr3d/swagger-assertions

Test your API requests and responses against your swagger definition

138850.9k5](/packages/fr3d-swagger-assertions)[imanghafoori/eloquent-mockery

Allows you to design your tests in an independent manner.

127636.4k2](/packages/imanghafoori-eloquent-mockery)[sofa/eloquent-testsuite

Helpers for fast and reliable UNIT tests for your Eloquent Models with PHPUnit

10104.7k](/packages/sofa-eloquent-testsuite)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
