tkaratug/eloquent-scope-assertion 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

tkaratug/eloquent-scope-assertion

Composer 安装命令:

composer require tkaratug/eloquent-scope-assertion

包简介

Eloquent scope assertion for testing Laravel applications.

README 文档

README

Latest Version on Packagist Total Downloads

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

Installation

You can install the package via composer:

composer require tkaratug/eloquent-scope-assertion

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

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

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email tkaratug@hotmail.com.tr instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

tkaratug/eloquent-scope-assertion 适用场景与选型建议

tkaratug/eloquent-scope-assertion 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 345 次下载、GitHub Stars 达 18, 最近一次更新时间为 2022 年 04 月 24 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「test」 「assertion」 「laravel」 「eloquent」 「scope」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 tkaratug/eloquent-scope-assertion 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 tkaratug/eloquent-scope-assertion 我们能提供哪些服务?
定制开发 / 二次开发

基于 tkaratug/eloquent-scope-assertion 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 345
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 18
  • 点击次数: 11
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 18
  • Watchers: 1
  • Forks: 1
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2022-04-24