
# الاختبار

يوفر Queuety فئة `QueueFake` تستبدل قائمة الانتظار الحقيقية بمخزن داخل الذاكرة. تُسجَّل الوظائف المرسلة بدلًا من كتابتها في قاعدة البيانات، كما يسجل `create_batch()` بيانات الدُفعات الوصفية في الذاكرة. يتيح لك ذلك التحقق من سلوك الإرسال دون تشغيل العمال أو الكتابة إلى قاعدة البيانات. يظل الإرسال باسم المعالج يحلّ المعالج عبر السجل، لذا استدعِ `Queuety::init()` أولًا عند الإرسال بمعالج نصي؛ أما مثيلات `Contracts\Job` و`chain()` و`create_batch()` و`batch()` فتعمل من دونه.

## إعداد البديل الوهمي

استدعِ `Queuety::fake()` في بداية الاختبار. فهو يعيد مثيلًا من `QueueFake` يسجل كل عمليات الإرسال اللاحقة.

```php
use Queuety\Queuety;

class SendEmailTest extends \PHPUnit\Framework\TestCase {
    protected function setUp(): void {
        $this->fake = Queuety::fake();
    }

    protected function tearDown(): void {
        Queuety::reset();
    }
}
```

ينشئ `Queuety::fake()` مثيلًا جديدًا من `QueueFake` ويربطه بواجهة `Queuety`. ويسجل `Queuety::dispatch()` و`Dispatchable::dispatch()` الوظائف المدفوعة. ويسجل `Queuety::chain()` كل وظيفة متسلسلة كعملية دفع عادية حسب ترتيب الإرسال. ويسجل `Queuety::create_batch()` الوظائف المدفوعة والبيانات الوصفية للدُفعات التي يستخدمها `assert_batched()`. ويسجل `Queuety::batch()` الوظائف المدفوعة، لكنه لا ينشئ بيانات وصفية وهمية للدُفعات.

استدعِ `Queuety::reset()` في `tearDown()` لمسح البديل الوهمي بين الاختبارات. يمسح ذلك كل حالة الواجهة، لذا استدعِ `Queuety::init()` مرة أخرى إذا احتاج اختبار لاحق إلى قائمة الانتظار الحقيقية.

## التحقق من دفع الوظائف

### `assert_pushed()`

تحقق من إرسال فئة وظيفة معينة مرة واحدة على الأقل.

```php
public function test_welcome_email_is_sent(): void {
    $this->fake = Queuety::fake();

    // Code under test...
    register_new_user( 'user@example.com' );

    $this->fake->assert_pushed( SendWelcomeEmailJob::class );
}
```

مرر دالة اختيارية لتصفية النتائج حسب الحمولة أو السمات الأخرى. تتلقى الدالة مصفوفة بيانات الوظيفة المسجلة بمفاتيح `handler` و`payload` و`queue` و`instance`. تكون `instance` هي `null` للوظائف المرسلة عبر الواجهة أو السمة `Dispatchable`، لذا طابِق باستخدام `handler` و`payload`.

```php
$this->fake->assert_pushed( SendWelcomeEmailJob::class, function ( array $job ) {
    return $job['payload']['to'] === 'user@example.com';
} );
```

### `assert_pushed_times()`

تحقق من دفع وظيفة عددًا محددًا من المرات.

```php
$this->fake->assert_pushed_times( SendEmailJob::class, 3 );
```

### `assert_not_pushed()`

تحقق من عدم إرسال أي وظيفة مطلقًا.

```php
$this->fake->assert_not_pushed( DeleteAccountJob::class );
```

### `assert_nothing_pushed()`

تحقق من عدم إرسال أي وظائف على الإطلاق.

```php
public function test_no_jobs_on_invalid_input(): void {
    $this->fake = Queuety::fake();

    process_input( '' ); // invalid, should not dispatch anything

    $this->fake->assert_nothing_pushed();
}
```

## التحقق من الدُفعات

### `assert_batched()`

تحقق من إرسال دفعة. ويمكنك تمرير دالة اختيارية لتصفية النتائج حسب محتوى الدفعة.

```php
$this->fake->assert_batched();

$this->fake->assert_batched( function ( array $batch ) {
    return count( $batch['jobs'] ) === 3;
} );
```

تتلقى الدالة مصفوفة بمفتاحي `jobs` و`options`.

## فحص الوظائف المدفوعة

استخدم `pushed()` لاسترداد كل عمليات الإرسال المسجلة لفئة معينة، و`batches()` لاسترداد كل الدُفعات المسجلة.

```php
$emails = $this->fake->pushed( SendEmailJob::class );
// [ ['handler' => '...', 'payload' => [...], 'queue' => 'default', 'instance' => null], ... ]

$batches = $this->fake->batches();
// [ ['jobs' => [...], 'options' => [...]], ... ]
```

## إعادة الضبط بين الاختبارات

استدعِ `reset()` على البديل الوهمي لمسح كل الوظائف والدُفعات المسجلة دون إنشاء مثيل جديد.

```php
$this->fake->reset();
```

أو استدعِ `Queuety::reset()` لهدم البديل الوهمي بالكامل وكل حالته الداخلية.

## مثال كامل

```php
use PHPUnit\Framework\TestCase;
use Queuety\Queuety;

class OrderWorkflowTest extends TestCase {
    private \Queuety\Testing\QueueFake $fake;

    protected function setUp(): void {
        $this->fake = Queuety::fake();
    }

    protected function tearDown(): void {
        Queuety::reset();
    }

    public function test_order_dispatches_payment_job(): void {
        $order = create_order( [ 'total' => 99.99 ] );

        $this->fake->assert_pushed( ProcessPaymentJob::class, function ( array $job ) use ( $order ) {
            return $job['payload']['order_id'] === $order->id;
        } );
        $this->fake->assert_not_pushed( RefundJob::class );
    }

    public function test_bulk_import_dispatches_batch(): void {
        start_bulk_import( $rows );

        $this->fake->assert_batched( function ( array $batch ) use ( $rows ) {
            return count( $batch['jobs'] ) === count( $rows );
        } );
    }

    public function test_nothing_dispatched_without_data(): void {
        process_empty_queue();

        $this->fake->assert_nothing_pushed();
    }
}
```
