
# Тестування

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`. Для завдань, надісланих через фасад або трейт `Dispatchable`, значенням `instance` є `null`, тому шукайте за `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();
    }
}
```
