framework icon indicating copy to clipboard operation
framework copied to clipboard

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

Open tontonsb opened this issue 1 week ago • 2 comments

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.

tontonsb avatar Dec 08 '25 08:12 tontonsb