seregazhuk/react-promise-testing

PHPUnit-based library for testing ReactPHP promises

v0.6.1 2021-04-22 20:18 UTC

This package is auto-updated.

Last update: 2024-10-13 02:43:33 UTC


README

A library that provides a set of convenient assertions for testing ReactPHP promises. Under the hood uses clue/php-block-react to block promises.

Build Status Maintainability Test Coverage Total Downloads

When testing asynchronous code and promises things can be a bit tricky. This library provides a set of convenient assertions for testing ReactPHP promises.

Table of Contents

Installation

Dependencies

Library requires PHP 8.0 or above.

The recommended way to install this library is via Composer. New to Composer?

See also the CHANGELOG for details about version upgrades.

composer require seregazhuk/react-promise-testing --dev

Quick Start

Use the trait seregazhuk\React\PromiseTesting\AssertsPromise or extend your test classes from seregazhuk\React\PromiseTesting\TestCase class, which itself extends PHPUnit TestCase.

final class MyTest extends TestCase
{
    /** @test */
    public function promise_fulfills_with_a_response_object()
    {
        $browser = new Clue\React\Buzz\Browser($this->eventLoop());
        $promise = $browser->get('http://www.google.com/');
        $this->assertPromiseFulfillsWithInstanceOf($promise, ResponseInterface::class);
    }
}

Using the trait:

use PHPUnit\Framework\TestCase;
use seregazhuk\React\PromiseTesting\AssertsPromise;

final class MyTest extends TestCase
{
    use AssertsPromise;

    /** @test */
    public function promise_fulfills_with_a_response_object()
    {
        $browser = new Clue\React\Buzz\Browser($this->eventLoop());
        $promise = $browser->get('http://www.google.com/');
        $this->assertPromiseFulfillsWithInstanceOf($promise, ResponseInterface::class);
    }
}

Test above checks that a specified promise fulfills with an instance of ResponseInterface.

Event loop

To make promise assertions we need to run the loop. Before each test a new instance of the event loop is being created (inside setUp() method). If you need the loop to build your dependencies you should use eventLoop() method to retrieve it.

Assertions

assertPromiseFulfills()

public function assertPromiseFulfills(PromiseInterface $promise, int $timeout = null): void

The test fails if the $promise rejects.

You can specify $timeout in seconds to wait for promise to be resolved. If the promise was not fulfilled in specified timeout the test fails. When not specified, timeout is set to 2 seconds.

final class PromiseFulfillsTest extends TestCase
{
    /** @test */
    public function promise_fulfills(): void
    {
        $deferred = new Deferred();
        $deferred->reject();
        $this->assertPromiseFulfills($deferred->promise(), 1);
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 189 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\PromiseFulfillTest::promise_fulfills
Failed asserting that promise fulfills. Promise was rejected.

assertPromiseFulfillsWith()

assertPromiseFulfillsWith(PromiseInterface $promise, $value, int $timeout = null): void

The test fails if the $promise doesn't fulfills with a specified $value.

You can specify $timeout in seconds to wait for promise to be fulfilled. If the promise was not fulfilled in specified timeout the test fails. When not specified, timeout is set to 2 seconds.

final class PromiseFulfillsWithTest extends TestCase
{
    /** @test */
    public function promise_fulfills_with_a_specified_value(): void
    {
        $deferred = new Deferred();
        $deferred->resolve(1234);
        $this->assertPromiseFulfillsWith($deferred->promise(), 1);
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 180 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\PromiseFulfillsWithTest::promise_fulfills_with_a_specified_value
Failed asserting that promise fulfills with a specified value. 
Failed asserting that 1234 matches expected 1.

assertPromiseFulfillsWithInstanceOf()

assertPromiseFulfillsWithInstanceOf(PromiseInterface $promise, string $class, int $timeout = null): void

The test fails if the $promise doesn't fulfills with an instance of specified $class.

You can specify $timeout in seconds to wait for promise to be fulfilled. If the promise was not fulfilled in specified timeout the test fails. When not specified, timeout is set to 2 seconds.

final class PromiseFulfillsWithInstanceOfTest extends TestCase
{
    /** @test */
    public function promise_fulfills_with_an_instance_of_class(): void
    {
        $deferred = new Deferred();
        $deferred->resolve(new MyClass);
        $this->assertPromiseFulfillsWithInstanceOf($deferred->promise(), MyClass::class);
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 180 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\PromiseFulfillsWithWithInstanceOfTest::promise_fulfills_with_an_instance_of_class
Failed asserting that promise fulfills with a value of class MyClass. 

assertPromiseRejects()

assertPromiseRejects(PromiseInterface $promise, int $timeout = null): void

The test fails if the $promise fulfills.

You can specify $timeout in seconds to wait for promise to be resolved. If the promise was not fulfilled in specified timeout, it rejects with React\Promise\Timer\TimeoutException. When not specified, timeout is set to 2 seconds.

final class PromiseRejectsTest extends TestCase
{
    /** @test */
    public function promise_rejects(): void
    {
        $deferred = new Deferred();
        $deferred->resolve();
        $this->assertPromiseRejects($deferred->promise());
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 175 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\PromiseRejectsTest::promise_rejects
Failed asserting that promise rejects. Promise was fulfilled.

assertPromiseRejectsWith()

assertPromiseRejectsWith(PromiseInterface $promise, string $reasonExceptionClass, int $timeout = null): void

The test fails if the $promise doesn't reject with a specified exception class.

You can specify $timeout in seconds to wait for promise to be resolved. If the promise was not fulfilled in specified timeout, it rejects with React\Promise\Timer\TimeoutException. When not specified, timeout is set to 2 seconds.

final class PromiseRejectsWithTest extends TestCase
{
    /** @test */
    public function promise_rejects_with_a_specified_reason(): void
    {
        $deferred = new Deferred();
        $deferred->reject(new \LogicException());
        $this->assertPromiseRejectsWith($deferred->promise(), \InvalidArgumentException::class);
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 136 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\PromiseRejectsWithTest::promise_rejects_with_a_specified_reason
Failed asserting that promise rejects with a specified reason.
Failed asserting that LogicException Object (...) is an instance of class "InvalidArgumentException".

assertTrueAboutPromise()

assertTrueAboutPromise(PromiseInterface $promise, callable $predicate, int $timeout = null): void

The test fails if the value encapsulated in the Promise does not conform to an arbitrary predicate.

You can specify $timeout in seconds to wait for promise to be resolved. If the promise was not fulfilled in specified timeout, it rejects with React\Promise\Timer\TimeoutException. When not specified, timeout is set to 2 seconds.

final class AssertTrueAboutPromiseTest extends TestCase
{
    /** @test */
    public function promise_encapsulates_integer(): void
    {
        $deferred = new Deferred();
        $deferred->resolve(23);

        $this->assertTrueAboutPromise($deferred->promise(), function ($val) {
            return is_object($val);
        });
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 136 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\AssertTrueAboutPromiseTest::promise_encapsulates_integer
Failed asserting that false is true.

assertFalseAboutPromise()

assertFalseAboutPromise(PromiseInterface $promise, callable $predicate, int $timeout = null): void

The test fails if the value encapsulated in the Promise conforms to an arbitrary predicate.

You can specify $timeout in seconds to wait for promise to be resolved. If the promise was not fulfilled in specified timeout, it rejects with React\Promise\Timer\TimeoutException. When not specified, timeout is set to 2 seconds.

final class AssertFalseAboutPromiseTest extends TestCase
{
    /** @test */
    public function promise_encapsulates_object(): void
    {
        $deferred = new Deferred();
        $deferred->resolve(23);

        $this->assertFalseAboutPromise($deferred->promise(), function ($val) {
            return is_int($val);
        });
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 136 ms, Memory: 4.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\AssertFalseAboutPromiseTest::promise_encapsulates_object
Failed asserting that true is false.

Helpers

waitForPromiseToFulfill()

function waitForPromiseToFulfill(PromiseInterface $promise, int $timeout = null).

This helper can be used when you want to resolve a promise and get the resolution value.

Tries to resolve a $promise in a specified $timeout seconds and returns resolved value. If $timeout is not set uses 2 seconds by default. The test fails if the $promise doesn't fulfill.

final class WaitForPromiseToFulfillTest extends TestCase
{
    /** @test */
    public function promise_fulfills(): void
    {
        $deferred = new Deferred();

        $deferred->reject(new \Exception());
        $value = $this->waitForPromiseToFulfill($deferred->promise());
    }
}
PHPUnit 8.5.2 by Sebastian Bergmann and contributors.

F                                                                   1 / 1 (100%)

Time: 223 ms, Memory: 6.00MB

There was 1 failure:

1) seregazhuk\React\PromiseTesting\tests\WaitForPromiseToFulfillTest::promise_fulfills
Failed to fulfill a promise. It was rejected with Exception.

waitForPromise()

function waitForPromise(PromiseInterface $promise, int $timeout = null).

Tries to resolve a specified $promise in a specified $timeout seconds. If $timeout is not set uses 2 seconds by default. If the promise fulfills returns a resolution value, otherwise throws an exception. If the promise rejects throws the rejection reason, if the promise doesn't fulfill in a specified $timeout throws React\Promise\Timer\TimeoutException.

This helper can be useful when you need to get the value from the fulfilled promise in a synchronous way:

$value = $this->waitForPromise($cache->get('key'));