Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

davorminchorov's avatar

Http::fake() is ignored and the real HTTP request is being fired to an external API

Hi,

I am trying to test some external API calls with a fake call using the Http client that Laravel provides out of the box, but for some reason I am not getting the fake version that I have specified, instead it just proceeds to hit the API for some reason.

Here's an example code in my test:

$http = app(Factory::class);
$http->fake(function ($request) use($http) {
    return $http->response(['Status' => 0], Response::HTTP_OK);
});

After this I do something like:

$response = $this->postJson('my-url', $attributes);

and I get the original response from the external API instead of the fake one that i specified in my test.

Anyone have any ideas what am I missing?

0 likes
10 replies
bobbybouwmann's avatar
Level 88

Http::fake only works if you're actually using the Http class in your code.It doesn't catch all outgoing HTTP calls in your application.

$response = Http::post('my-url');

If you do this, fake should work correctly here.

davorminchorov's avatar

That’s interesting, because for other similar tests, I don’t use the facade (Storage for example) and it works, but it does not work for Http.

davorminchorov's avatar

Ok so I switched my Factory class to use the Http facade instead and it is working as expected.

Is there an alternative way to use dependency injection for the Http client class?

davorminchorov's avatar

I solved it by using the facade as a dependency in the constructor, it's close enough to what I am looking for.

carobiscuit's avatar

@ruffles would you be willing to share the full test example? i'm having some issues with this as well and can't seem to get it going

kspdev's avatar

@davorminchorov I did not understand how you were using the app function in your original post:

$http = app(Factory::class);

I understand it's using a Laravel service container. But how is it returning an Http client object without mentioning the Http facade name? And what is the advantage of using it instead of Http::fake ?

I am just an amateur dev trying to learn more here 😊 Appreciate any help or links to articles on the same.

rvwoens's avatar

@kspdev Factory is actually Illuminate\Http\Client\Factory so it is the Http factory. Should have been called HttpFactory. app(..) instantiates the object the Laravel way. Same as app()->make(..)

mronx's avatar

@davorminchorov I found a solution. On my test case there is beforeEach:

beforeEach(function () {
    ['message' => $this->message, 'chat' => $this->chat, 'lead' => $this->lead] = createLeadDetailsWithChat();
    Http::fake([
        'https://api.openai.com/v1/*' => Http::response([
            'choices' => [
                [
                    'message' => 'Hello',
                    'finish_reason' => 'stop'
                ],
            ],
        ]),
    ]);
    $this->service = app(AIConversationService::class);
});

And I have test:

test('it should return success next message', function () {
    $this->chat->responsible = ChatResponsibleType::AI;
    $this->chat->save();

    $this->chat->messages()->create([
        'message' => $this->message,
        'sender' => ChatSender::CLIENT,
        'chat_type' => ChatType::WHATSAPP,
    ]);

    $this->chat->refresh();

    $nextMessage = $this->service->getChatResponse($this->chat, ChatType::WHATSAPP);

    expect($nextMessage)->toBeString();
});

If I move Http:fake from beforeEach to my test it didn't work because Http is creating on my app(AIConversationService::class) here. So Http::fake should be created before create and object of Http

Please or to participate in this conversation.