I'm writing a feature test in which I need to fake multiple requests.
Currently, when I run the test, only the first request is actually faked, any other request not.
After some searching, I came across this Playground and found out that one can use the swap() method to reset the fake instance: https://laravelplayground.com/#/snippets/ffb7f281-5345-4a26-b94f-7e5cb8a58514
I tried this out, but it doesn't seem so work (Laravel 9)? I copied the code in my test, and when I dump the response, it still dumps the first response twice.
Any help here?
Code:
Http::fake([
'https://login.bol.com/token' => Http::response(json_encode($response)),
]);
$fake = app(\Illuminate\Http\Client\Factory::class);
Http::swap($fake);
foreach ($this->orders() as $order) {
Http::fake([
"https://api.bol.com/retailer-demo/orders/{$order}" => Http::response(['foo' => 'bar']),
]);
$this->client->getOrder($user, $order); // $this->client does a Http request
}
Code I'm trying to test:
class Client extends BaseClient
{
public function getOrder(User $user, string $orderId): ?array
{
$this->authenticate($user);
$this->get($orderId); // Method in the BaseClient which does a request using HttpClient
}
protected function authenticate(User $user): void
{
$this->setAccessToken($user);
}
}
class BaseClient
{
protected AccessToken $accessToken;
protected function setAccessToken(User $user): void
{
$accessToken = $this->getAccessToken($user);
if (empty($this->accessToken)) {
$this->accessToken = $accessToken;
return;
}
if ($this->accessToken !== $accessToken) {
$this->accessToken = $accessToken;
}
}
protected function getAccessToken(User $user): ?AccessToken
{
try {
$credentials = $user->getCredentials();
$accessToken = $credentials->accessToken;
if (null === $accessToken) {
return $this->requestAccessToken($credentials);
}
if (now() > $accessToken->expires_at) {
$accessToken->delete();
return $this->requestAccessToken($credentials);
}
return $accessToken;
} catch (\Exception $e) {
report($e);
return null;
}
}
private function requestAccessToken(Credential $credential): ?AccessToken
{
try {
$authClient = new AuthClient(
credential: $credential
);
$authClient->authenticate();
$token = $authClient->getToken();
return $credential->accessToken()->create([
'access_token' => $token['access_token'],
'expires_at' => $token['expires_at'],
]);
} catch (\Exception $e) {
report($e);
return null;
}
}
}
Ultimately, I'm trying to assert that only one AccessToken is requested, created and used, as long as it's not expired.