Тестирование
Queuety предоставляет класс QueueFake, который заменяет реальную очередь хранилищем в памяти. Отправленные задачи записываются вместо сохранения в базе данных; create_batch() также хранит метаданные пакетов в памяти. Это позволяет проверять отправку задач, не запуская рабочие процессы и не записывая данные в базу. При отправке по имени обработчика он по-прежнему определяется через реестр, поэтому перед отправкой строкового имени обработчика вызовите Queuety::init(); экземпляры Contracts\Job, chain(), create_batch() и batch() работают без этого.
Настройка подмены очереди
Вызовите Queuety::fake() в начале теста. Метод возвращает экземпляр QueueFake, который записывает все последующие отправки задач.
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()
Проверьте, что задача определенного класса была отправлена хотя бы один раз.
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.
$this->fake->assert_pushed( SendWelcomeEmailJob::class, function ( array $job ) {
return $job['payload']['to'] === 'user@example.com';
} );
assert_pushed_times()
Проверьте, что задача была добавлена ровно указанное количество раз.
$this->fake->assert_pushed_times( SendEmailJob::class, 3 );
assert_not_pushed()
Проверьте, что задача ни разу не была отправлена.
$this->fake->assert_not_pushed( DeleteAccountJob::class );
assert_nothing_pushed()
Проверьте, что задачи вообще не отправлялись.
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()
Проверьте, что пакет был отправлен. При необходимости передайте функцию обратного вызова для фильтрации по содержимому пакета.
$this->fake->assert_batched();
$this->fake->assert_batched( function ( array $batch ) {
return count( $batch['jobs'] ) === 3;
} );
Функция обратного вызова получает массив с ключами jobs и options.
Просмотр добавленных задач
Используйте pushed(), чтобы получить все записанные отправки задач указанного класса, и batches(), чтобы получить все записанные пакеты.
$emails = $this->fake->pushed( SendEmailJob::class );
// [ ['handler' => '...', 'payload' => [...], 'queue' => 'default', 'instance' => null], ... ]
$batches = $this->fake->batches();
// [ ['jobs' => [...], 'options' => [...]], ... ]
Сброс между тестами
Вызовите reset() для подмены, чтобы очистить все записанные задачи и пакеты без создания нового экземпляра.
$this->fake->reset();
Или вызовите Queuety::reset(), чтобы полностью удалить подмену и все ее внутреннее состояние.
Полный пример
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();
}
}