
# Testes

Queuety fornece uma classe `QueueFake` que substitui a fila real por um armazenamento em memória. As tarefas despachadas são registradas em vez de gravadas no banco de dados, e `create_batch()` também registra os metadados dos lotes em memória. Assim, você pode verificar o comportamento do despacho sem executar workers nem gravar no banco de dados. O despacho pelo nome do handler ainda resolve o handler por meio do registro, então chame `Queuety::init()` antes de despachar handlers por string; instâncias de `Contracts\Job`, `chain()`, `create_batch()` e `batch()` funcionam sem isso.

## Configurando a simulação

Chame `Queuety::fake()` no início do teste. Ele retorna uma instância de `QueueFake` que registra todos os despachos seguintes.

```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()` cria um novo `QueueFake` e o conecta à fachada `Queuety`. `Queuety::dispatch()` e `Dispatchable::dispatch()` registram as tarefas enviadas. `Queuety::chain()` registra cada tarefa encadeada como um envio normal, na ordem do despacho. `Queuety::create_batch()` registra tanto as tarefas enviadas quanto os metadados do lote usados por `assert_batched()`. `Queuety::batch()` registra as tarefas enviadas, mas não cria metadados de lote simulados.

Chame `Queuety::reset()` em `tearDown()` para limpar a simulação entre testes. Isso limpa todo o estado da fachada; portanto, chame `Queuety::init()` novamente se um teste posterior precisar da fila real.

## Verificando se as tarefas foram enviadas

### `assert_pushed()`

Verifique se uma classe de tarefa específica foi despachada pelo menos uma vez.

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

Passe um callback opcional para filtrar pelo payload ou por outros atributos. O callback recebe o array de dados da tarefa registrada com as chaves `handler`, `payload`, `queue` e `instance`. `instance` é `null` para tarefas despachadas pela fachada ou pelo trait `Dispatchable`; portanto, use `handler` e `payload` para filtrar.

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

### `assert_pushed_times()`

Verifique se uma tarefa foi enviada exatamente um determinado número de vezes.

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

### `assert_not_pushed()`

Verifique se uma tarefa nunca foi despachada.

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

### `assert_nothing_pushed()`

Verifique se nenhuma tarefa foi despachada.

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

## Verificando lotes

### `assert_batched()`

Verifique se um lote foi despachado. Opcionalmente, passe um callback para filtrar pelo conteúdo do lote.

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

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

O callback recebe um array com as chaves `jobs` e `options`.

## Inspecionando tarefas enviadas

Use `pushed()` para obter todos os despachos registrados de uma determinada classe e `batches()` para obter todos os lotes registrados.

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

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

## Limpando entre testes

Chame `reset()` na simulação para limpar todas as tarefas e lotes registrados sem criar uma nova instância.

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

Ou chame `Queuety::reset()` para encerrar completamente a simulação e todo o estado interno.

## Exemplo completo

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