⛽ Set of utilities to test Laravel applications powered by Octane.

Overview

Octane Testbench

Author PHP Version Laravel Version Octane Compatibility Build Status Coverage Status Quality Score Latest Version Software License PSR-12 Total Downloads

Set of utilities to test Laravel applications powered by Octane.

Install

Via Composer:

composer require --dev cerbero/octane-testbench

In tests/TestCase.php, use the TestsOctaneApplication trait:

use Cerbero\OctaneTestbench\TestsOctaneApplication;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use TestsOctaneApplication;
}

Now all tests extending this class, even previously created tests, can run on Octane.

Usage

In a nutshell, Octane Testbench

  1. is progressive: existing tests keep working, making Octane adoption easier for existing Laravel apps
  2. stubs out workers and clients: tests don't need a Swoole or RoadRunner server to run
  3. preserves the application state after a request, so assertions can be performed after the response
  4. offers fluent assertions tailored to Octane:
public function test_octane_application()
{
    $this
        ->assertOctaneCacheMissing('foo')
        ->assertOctaneTableMissing('example', 'row')
        ->assertOctaneTableCount('example', 0)
        ->expectsConcurrencyResults([1, 2, 3])
        ->get('octane/route')
        ->assertOk()
        ->assertOctaneCacheHas('foo', 'bar')
        ->assertOctaneTableHas('example', 'row.votes', 123)
        ->assertOctaneTableCount('example', 1);
}

Requests and responses

HTTP requests are performed with the same methods we would normally call to test any Laravel application, except they will work for both standard and Octane routes:

Route::get('web-route', fn () => 123);

Octane::route('POST', '/octane-route', fn () => new Response('foo'));


public function test_web_route()
{
    $this->get('web-route')->assertOk()->assertSee('123');
}

public function test_octane_route()
{
    $this->post('octane-route')->assertOk()->assertSee('foo');
}

Responses are wrapped in a ResponseTestCase instance that lets us call response assertions, any assertion of the Laravel testing suite and the following exception assertions:

$this
    ->get('failing-route')
    ->assertException(Exception::class) // assert exception instance
    ->assertException(new Exception('message')) // assert exception instance and message
    ->assertExceptionMessage('message'); // assert exception message

Furthermore, responses and exceptions can be debugged by calling the dd() and dump() methods:

$this
    ->get('failing-route')
    ->dump() // dump the whole response/exception
    ->dump('original') // dump only a specific property
    ->dd() // dump-and-die the whole response/exception
    ->dd('headers'); // dump-and-die only a specific property

Concurrency

Concurrency works fine during tests. However, PHP 8 forbids the serialization of reflections (hence mocks) and concurrent tasks are serialized before being dispatched. If tasks involve mocks, we can fake the concurrency:

// code to test:
Octane::concurrently([
    fn () => $mockedService->run(),
    fn () => 123,
]);

// test:
$this
    ->mocks(Service::class, ['run' => 'foo'])
    ->expectsConcurrency()
    ->get('route');

In the test above we are running tasks sequentially without serialization, allowing mocked methods to be executed (we will see more about mocks later).

If we need more control over how concurrent tasks run, we can pass a closure to expectsConcurrency(). For example, the test below runs only the first task:

$this
    ->expectsConcurrency(fn (array $tasks) => [ $tasks[0]() ])
    ->get('route');

To manipulate the results of concurrent tasks, we can use expectsConcurrencyResults():

$this
    ->expectsConcurrencyResults([$firstTaskResult, $secondTaskResult])
    ->get('route');

Finally we can make concurrent tasks fail to test our code when something wrong happens:

$this
    ->expectsConcurrencyException() // tasks fail due to a generic exception
    ->get('route');

$this
    ->expectsConcurrencyException(new Exception('message')) // tasks fail due to a specific exception
    ->get('route');

$this
    ->expectsConcurrencyTimeout() // tasks fail due to a timeout
    ->get('route');

Cache

Octane Testbench provides the following assertions to test the Octane cache:

$this
    ->assertOctaneCacheMissing($key) // assert the key is not set
    ->get('route')
    ->assertOctaneCacheHas($key) // assert the key is set
    ->assertOctaneCacheHas($key, $value); // assert the key has the given value

Tables

Octane tables can be tested with the following assertions:

$this
    ->assertOctaneTableMissing($table, $row) // assert the row is not present in the table
    ->assertOctaneTableCount($table, 0) // assert the number of rows in the table
    ->get('route')
    ->assertOctaneTableHas($table, $row) // assert the row is present in the table
    ->assertOctaneTableHas($table, 'row.column' $value) // assert the column in the row has the given value
    ->assertOctaneTableCount($table, 1);

Events

By default listeners for the Octane RequestReceived event are disabled to perform assertions on the application state. However we can register listeners for any Octane event if need be:

$this
    ->listensTo(RequestReceived::class, $listener1, $listener2) // register 2 listeners for RequestReceived
    ->get('route');

$this
    ->stopsListeningTo(TaskReceived::class, $listener1, $listener2) // unregister 2 listeners for TaskReceived
    ->get('route');

Container

Octane Testbench also introduces the following helpers to bind and mock services at the same time while preserving a fluent syntax:

$this
    ->mocks(Service::class, ['expectedMethod' => $expectedValue]) // mock with simple expectations
    ->mocks(Service::class, fn ($mock) => $mock->shouldReceive('method')->twice()) // mock with advanced expectations
    ->partiallyMocks(Service::class, ['expectedMethod' => $expectedValue]) // same as above but partial
    ->partiallyMocks(Service::class, fn ($mock) => $mock->shouldReceive('method')->twice())
    ->get('route');

Change log

Please see CHANGELOG for more information on what has changed recently.

Testing

composer test

Contributing

Please see CONTRIBUTING and CODE_OF_CONDUCT for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

You might also like...
Durable workflow engine that allows users to write long running persistent distributed workflows in PHP powered by Laravel queues

Durable workflow engine that allows users to write long running persistent distributed workflows (orchestrations) in PHP powered by Laravel queues. Inspired by Temporal and Azure Durable Functions.

Ani Cast - Anime List & Trending App. (Powered by Jikan API)

(Under Development) Ani Cast - Anime Shows App.

Package to easily test crudable controllers for Laravel based API

Laravel Crudable Test This package is very usefull to easily test crudable controllers. Installation You can install package via composer. Add reposit

A light weight laravel package that facilitates dealing with arabic concepts using a set of classes and methods to make laravel speaks arabic

A light weight laravel package that facilitates dealing with arabic concepts using a set of classes and methods to make laravel speaks arabic! concepts like , Hijri Dates & Arabic strings and so on ..

Lightflows Technical Test

Installation git clone composer install cp .env.example .env php artisan key:generate setup database in .env php artisan migrate --seed php artisan pa

🧾 Online test site with the human sciences theme. Using: HTML5, CSS3, Js., PHP7 and MySQL. 🚀
🧾 Online test site with the human sciences theme. Using: HTML5, CSS3, Js., PHP7 and MySQL. 🚀

form-ciencias-humanas 🚀 Technologies Lunacy HTML5 CSS3 PHP7 MYSQL Animate.css Illustrations from icons8: Earth care from Anna Antipina Earth and Moon

A set of useful Laravel collection macros
A set of useful Laravel collection macros

A set of useful Laravel collection macros This repository contains some useful collection macros. Spatie is a webdesign agency based in Antwerp, Belgi

Update multiple Laravel Model records, each with it's own set of values, sending a single query to your database!

Laravel Mass Update Update multiple Laravel Model records, each with its own set of values, sending a single query to your database! Installation You

Cagilo - a set of simple components for use in your views Laravel Blade.

Cagilo - a set of simple components for use in your views Laravel Blade. Official Documentation Documentation for Cagilo can be found on its we

Comments
  • Fix compatible ResponseTestCase

    Fix compatible ResponseTestCase

    Fatal error: Declaration of Illuminate\Testing\Fluent\Concerns\Debugging::dump(?string $prop = null) must be compatible with Illuminate\Testing\TestResponse::dump($key = null) in

    opened by faytekin 2
Owner
Andrea Marco Sartori
Andrea Marco Sartori
A High-Level Overview of Laravel Octane

This is the source code behind the Laracasts Larabit: A High-Level Overview of Laravel Octane, and features all of the files and code available in that video.

Andrew Schmelyun 1 Feb 10, 2022
An advanced Laravel integration for Bref, including Octane support.

Bref Laravel Bridge An advanced Laravel integration for Bref, including Octane support. This project is largely based on code from PHP Runtimes, Larav

CacheWerk 26 Dec 22, 2022
this package can help you to test race condition in Laravel Feature Test

Laravel Async Testing this package can help you to test race condition in Laravel Feature Test Requirements Laravel versions 5.7, 6.x, 7.x and 8.x PHP

Recca Tsai 61 Nov 5, 2022
Laravel-OvalFi helps you Set up, test, and manage your OvalFi integration directly in your Laravel App.

OvalFi Laravel Package Laravel-OvalFi helps you Set up, test, and manage your OvalFi integration directly in your Laravel App. Installation You can in

Paul Adams 2 Sep 8, 2022
Test your Laravel applications with phpspec

phpspec Laravel Extension phpspec extension for testing Laravel applications. Versions Depending on the version of Laravel and/or Phpspec you're using

Ben Constable 145 Sep 27, 2022
Utilities for laravel project

Sloth Utilities This package gives your Laravel projects some utilities that you might need for production. It's so simple to use, once it's installed

Sloth-Lab S.A.R.L 2 Nov 17, 2021
Builds nice, normalized and easy to consume REST JSON responses for Laravel powered APIs.

REST API Response Builder for Laravel Master branch: Development branch: Table of contents Introduction Why should I use it? Usage examples Features E

Marcin Orlowski 614 Dec 26, 2022
It's like React for PHP. Powered by Laravel, Livewire, Tailwind, & Alpine.

Tailwire It's like React for PHP. Powered by Laravel, Livewire, Tailwind, & Alpine. Features: Use a custom view component class namespace Declare rout

null 5 Dec 12, 2021
🧱 A Roblox clone written in PHP powered by the Laravel framework.

Laravel Roblox Clone Originally written in June-July 2021 to get better with Laravel and to have something fun to work on. If you need any help, feel

Snoot 6 Dec 19, 2022
Pronto Fuel is a heavilly opnionated starter kit for Laravel and Inertia.js powered by Vite

Pronto Fuel Pronto Fuel is a heavilly opnionated starter kit for Laravel and Inertia.js powered by Vite. It ships with autoimporting features and leve

null 87 Dec 28, 2022