Skip to content

Faking failed Http requests with Http::failedRequest() fails with another error #58043

@tontonsb

Description

@tontonsb

Laravel Version

12.41.1

PHP Version

8.3.17

Database Driver & Version

No response

Description

The documented way of failing HTTP client requests during tests doesn't seem to work.

The docs suggest adding this

Http::fake([
    'github.com/*' => Http::failedRequest(['code' => 'not_found'], 404),
]);

to fake a failed request. But instead of the request being failed or throwing an exception, an error is thrown as the tooling attempts to treat the exception as a promise and call a method that does not exist on it.

Here's the error as printed by the test runner:

   FAILED  Tests\Feature\ExampleTest > the application returns a successful response                            Error   
  Call to undefined method Illuminate\Http\Client\RequestException::then()

  at vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1400
    1396▕         return function ($handler) {
    1397▕             return function ($request, $options) use ($handler) {
    1398▕                 $promise = $handler($request, $options);
    1399▕ 
  ➜ 1400▕                 return $promise->then(function ($response) use ($request, $options) {
    1401▕                     $this->factory?->recordRequestResponsePair(
    1402▕                         (new Request($request))->withData($options['laravel_data']),
    1403▕                         $this->newResponse($response)
    1404▕                     );

      +17 vendor frames 
  18  tests/Feature/ExampleTest.php:19

Here's the dump of the error if I catch it:

Error {#1103
  #message: "Call to undefined method Illuminate\Http\Client\RequestException::then()"
  #code: 0
  #file: "./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php"
  #line: 1400
  trace: {
    ./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1400 { …}
    ./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1384 { …}
    ./vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php:35 { …}
    ./vendor/guzzlehttp/guzzle/src/Middleware.php:38 { …}
    ./vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php:71 { …}
    ./vendor/guzzlehttp/guzzle/src/Middleware.php:63 { …}
    ./vendor/guzzlehttp/guzzle/src/HandlerStack.php:75 { …}
    ./vendor/guzzlehttp/guzzle/src/Client.php:333 { …}
    ./vendor/guzzlehttp/guzzle/src/Client.php:169 { …}
    ./vendor/guzzlehttp/guzzle/src/Client.php:189 { …}
    ./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1224 { …}
    ./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:967 { …}
    ./vendor/laravel/framework/src/Illuminate/Support/helpers.php:424 { …}
    ./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:965 { …}
    ./vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:800 { …}
    ./vendor/laravel/framework/src/Illuminate/Http/Client/Factory.php:555 { …}
    ./vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:363 { …}
    ./tests/Feature/ExampleTest.php:20 {
      Tests\Feature\ExampleTest->test_the_application_returns_a_successful_response(): void^
      › try {
      ›     Http::get('https://github.com/laravel/framework');
      › } catch(\Throwable $e) {
    }
    ./vendor/phpunit/phpunit/src/Framework/TestCase.php:1657 { …}
    ./vendor/phpunit/phpunit/src/Framework/TestCase.php:515 { …}
    ./vendor/phpunit/phpunit/src/Framework/TestRunner/TestRunner.php:87 { …}
    ./vendor/phpunit/phpunit/src/Framework/TestCase.php:361 { …}
    ./vendor/phpunit/phpunit/src/Framework/TestSuite.php:369 { …}
    ./vendor/phpunit/phpunit/src/Framework/TestSuite.php:369 { …}
    ./vendor/phpunit/phpunit/src/Framework/TestSuite.php:369 { …}
    ./vendor/phpunit/phpunit/src/TextUI/TestRunner.php:64 { …}
    ./vendor/phpunit/phpunit/src/TextUI/Application.php:211 { …}
    ./vendor/phpunit/phpunit/phpunit:104 { …}
  }
} // tests/Feature/ExampleTest.php:22

Steps To Reproduce

Here's a minimal test that crashes on a fresh Laravel app, just put it in your tests/Feature/ExampleTest.php

<?php

namespace Tests\Feature;

use Illuminate\Support\Facades\Http;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response(): void
    {
        Http::fake([
            'github.com/*' => Http::failedRequest(['code' => 'not_found'], 404),
        ]);

        Http::get('https://github.com/laravel/framework');
    }
}

And run php artisan test.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions