Http::fake without an assertion tests that your code did not crash, which is not the same as testing that it called anything.
Http::fake([
'api.example/v1/*' => Http::response(['id' => 1], 201),
'*' => Http::response('', 500), // catch-all: fail loudly
]);
$this->service->sync($order);
Http::assertSent(function (Request $r) use ($order) {
return $r->url() === 'https://api.example/v1/orders'
&& $r['reference'] === $order->reference;
});
Http::assertSentCount(1);
The catch-all returning a 500 is the part worth copying: without it, a request to an unmatched URL returns an empty 200, so a typo in the endpoint passes the test. Asserting the count as well as the content catches the retry that fires twice, which is a bug the content assertion alone is blind to. assertNothingSent in the negative cases is equally worth writing, since it is the only way to test that a guard actually guarded.