
# テスト

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()`はプッシュされたジョブを記録しますが、偽装バッチメタデータは作成しません。

テスト間で偽装キューをリセットするには、`tearDown()`内で`Queuety::reset()`を呼び出します。ファサードの状態がすべて消去されるため、後のテストで実際のキューが必要な場合は、`Queuety::init()`を再度呼び出してください。

## ジョブのプッシュを検証する

### `assert_pushed()`

特定のジョブクラスが少なくとも1回ディスパッチされたことを検証します。

```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();
    }
}
```
