Skip to content

Commit

Permalink
Non matching requests should return a 200 ok by default (#9)
Browse files Browse the repository at this point in the history
* Non matching requests should return a 200 ok by default

* Update Readme

---------

Co-authored-by: Tom Harper <[email protected]>
  • Loading branch information
tomb1n0 and tomb1n0 authored May 19, 2023
1 parent 4d3d4a2 commit 7a3bfde
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 57 deletions.
20 changes: 17 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,20 @@ if ($response->successful()) {
}
```

Please note that once responses have been stubbed, un-stubbed requests will throw an exception.
### Preventing Stray Requests

By default the library will return a `200 OK` for any non-matched responses when faked. If you prefer, you can prevent stray requests:

```php
$client = $existingClient->fake()->preventStrayRequests();

try {
// Make a request which has not been stubbed
$response = $client->json('GET', 'https://dummyjson.com/products');
} catch (NoMatchingStubbedResponseException $e) {
// a NoMatchingStubbedResponseException exception will be thrown.
}
```

#### Asserting Requests

Expand Down Expand Up @@ -224,11 +237,12 @@ For example you could use the included `UrlMatcher` to check the method type
```php
class UrlMatcher implements FakeResponseMatcherContract
{
public function __construct(private string $url, private ?string $method = "GET")
public function __construct(private string $url, private ?string $method = 'GET')
{
}

public function match(RequestInterface $request): bool {
public function match(RequestInterface $request): bool
{
$requestUrl = (string) $request->getUri();
$requestMethod = $request->getMethod();

Expand Down
13 changes: 12 additions & 1 deletion src/Http/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,22 @@ public function __construct(
public function fake(): static
{
$copy = clone $this;
$copy->client = new FakePsr18Client();
$copy->client = new FakePsr18Client($this->responseFactory);

return $copy;
}

public function preventStrayRequests(): static
{
if (!$this->client instanceof FakePsr18Client) {
throw new ClientNotFakedException('Please call ->fake() first.');
}

$this->client->preventStrayRequests();

return $this;
}

/**
* Stub the given URL with the given fake response.
*
Expand Down
40 changes: 36 additions & 4 deletions src/Http/FakePsr18Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,44 @@
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Tomb1n0\GenericApiClient\Matchers\UrlMatcher;
use Tomb1n0\GenericApiClient\Contracts\FakeResponseMatcherContract;
use Tomb1n0\GenericApiClient\Exceptions\NoMatchingStubbedResponseException;

class FakePsr18Client implements ClientInterface
{
/**
* Used for generating the default response when not preventing stray requests.
*
* @var ResponseFactoryInterface
*/
protected ResponseFactoryInterface $responseFactory;

/**
* The stubbed responses, keyed by endpoint
*
* @var array<string, FakeResponse>
*/
protected array $stubs = [];

public function __construct()
/**
* Whether we should prevent stray requests.
*
* By default, we allow stray requests and just return a 200 OK for convenience.
*
* @var boolean
*/
protected bool $preventStrayRequests = false;

/**
* Create a new Fake Client.
*
* @param ResponseFactoryInterface $responseFactory
*/
public function __construct(ResponseFactoryInterface $responseFactory)
{
$this->responseFactory = $responseFactory;
$this->stubs = [];
}

Expand All @@ -28,6 +51,11 @@ public function stubResponse(string $url, FakeResponse $fakeResponse): void
$this->stubResponseWithCustomMatcher(new UrlMatcher($url), $fakeResponse);
}

public function preventStrayRequests(): void
{
$this->preventStrayRequests = true;
}

public function stubResponseWithCustomMatcher(
FakeResponseMatcherContract $matcher,
FakeResponse $fakeResponse,
Expand All @@ -45,9 +73,13 @@ public function sendRequest(RequestInterface $request): ResponseInterface
return $response->toPsr7Response();
}

throw new NoMatchingStubbedResponseException(
'No stubbed response for ' . $request->getMethod() . ' ' . $request->getUri(),
);
if ($this->preventStrayRequests) {
throw new NoMatchingStubbedResponseException(
'No stubbed response for ' . $request->getMethod() . ' ' . $request->getUri(),
);
}

return $this->responseFactory->createResponse(200);
}

private function findMatchingResponse(RequestInterface $request): ?FakeResponse
Expand Down
34 changes: 31 additions & 3 deletions tests/Client/FakeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class FakeTest extends BaseTestCase
{
/** @test */
public function faking_the_client_prevents_requests_from_being_sent_through_the_provided_psr18_client()
public function making_a_request_when_the_client_is_faked_and_not_a_matching_stub_found_will_return_a_200_ok()
{
$psr18Client = $this->mock(ClientInterface::class, function ($mock) {
$mock->shouldNotReceive('sendRequest');
Expand All @@ -23,6 +23,22 @@ public function faking_the_client_prevents_requests_from_being_sent_through_the_
$testingClient = $this->createTestingClient(psr18Client: $psr18Client);
$client = $testingClient->client->fake();

$response = $client->json('GET', 'https://example.com');

$this->assertSame(200, $response->status());
$this->assertSame('OK', $response->reason());
}

/** @test */
public function can_prevent_stray_requests()
{
$psr18Client = $this->mock(ClientInterface::class, function ($mock) {
$mock->shouldNotReceive('sendRequest');
});

$testingClient = $this->createTestingClient(psr18Client: $psr18Client);
$client = $testingClient->client->fake()->preventStrayRequests();

$this->expectException(NoMatchingStubbedResponseException::class);
$client->json('GET', 'https://example.com');
}
Expand All @@ -46,10 +62,10 @@ public function trying_to_stub_a_response_without_calling_fake_throws_an_excepti
}

/** @test */
public function faking_the_client_and_making_a_non_matching_request_will_throw_an_exception()
public function faking_the_client_and_making_a_non_matching_request_will_throw_an_exception_when_preventing_stray_requests()
{
$testingClient = $this->createTestingClient();
$client = $testingClient->client->fake();
$client = $testingClient->client->fake()->preventStrayRequests();

try {
$client->json('GET', 'https://example.com');
Expand All @@ -58,6 +74,18 @@ public function faking_the_client_and_making_a_non_matching_request_will_throw_a
}
}

/** @test */
public function faking_the_client_and_making_a_non_matching_request_will_return_a_200_ok_if_not_preventing_stray_requests()
{
$testingClient = $this->createTestingClient();
$client = $testingClient->client->fake();

$response = $client->json('GET', 'https://example.com');

$this->assertSame(200, $response->status());
$this->assertSame('OK', $response->reason());
}

/** @test */
public function can_stub_json_responses()
{
Expand Down
Loading

0 comments on commit 7a3bfde

Please sign in to comment.