Skip to content

Testing

Queuety provides a QueueFake class that replaces the real queue with an in-memory store. Dispatched jobs are recorded instead of being written to the database, and create_batch() records batch metadata in memory as well. That lets you assert dispatch behavior without running workers or writing to the database. Dispatching by handler name still resolves the handler through the registry, so call Queuety::init() first for string-handler dispatches; Contracts\Job instances, chain(), create_batch(), and batch() work without it.

Setting up the fake

Call Queuety::fake() at the start of your test. It returns a QueueFake instance that records all subsequent dispatches.

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() creates a new QueueFake and wires it into the Queuety facade. Queuety::dispatch() and Dispatchable::dispatch() record pushed jobs. Queuety::chain() records each chained job as a normal push in dispatch order. Queuety::create_batch() records both the pushed jobs and the batch metadata used by assert_batched(). Queuety::batch() records the pushed jobs, but it does not create fake batch metadata.

Call Queuety::reset() in tearDown() to clear the fake between tests. It clears all facade state, so call Queuety::init() again if a later test needs the real queue.

Asserting jobs were pushed

assert_pushed()

Assert that a specific job class was dispatched at least once.

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

Pass an optional callback to filter by payload or other attributes. The callback receives the recorded job data array with keys handler, payload, queue, and instance. instance is null for jobs dispatched through the facade or the Dispatchable trait, so match on handler and payload.

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

assert_pushed_times()

Assert that a job was pushed an exact number of times.

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

assert_not_pushed()

Assert that a job was never dispatched.

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

assert_nothing_pushed()

Assert that no jobs were dispatched at all.

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

Asserting batches

assert_batched()

Assert that a batch was dispatched. Optionally pass a callback to filter by batch contents.

PHP
$this->fake->assert_batched();

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

The callback receives an array with jobs and options keys.

Inspecting pushed jobs

Use pushed() to retrieve all recorded dispatches for a given class, and batches() to retrieve all recorded batches.

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

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

Resetting between tests

Call reset() on the fake to clear all recorded jobs and batches without creating a new instance.

PHP
$this->fake->reset();

Or call Queuety::reset() to fully tear down the fake and all internal state.

Full example

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