Reputation: 4484
I'm struggling to figure out what is probably something that's very basic and I'll get laughed out of here but I'm hoping maybe it'll help someone else as well.
I am trying to mock/test an Http
request in a feature test. I am still learning good/better/best techniques for testing so perhaps there is a much better way.
// MyFeatureTest.php
$user = factory(User::class)->create(['email' => '[email protected]']);
// Prevent actual request(s) from being made.
Http::fake();
$this->actingAs($user, 'api')
->getJson('api/v1/my/endpoint/123456')
->assertStatus(200);
In my controller my request looks like this:
public function myFunction() {
try {
$http = Http::withHeaders([
'Accept' => 'application/json',
'Access_Token' => 'my-token',
'Content-Type' => 'application/json',
])
->get('https://www.example.com/third-party-url, [
'foo' => 'bar,
]);
return new MyResource($http->json());
} catch (RequestException $exception) {
Log::error("Exception error: " . print_r($exception, true));
}
}
I would like to mock that I'm getting a 200 response, and ideally mock the expected json from the resource. I've successfully been able to do this test when the endpoint is local to my application (does not call to a 3rd party). This is what I've done in the past:
$http->assertStatus(200)
->assertJsonStructure([
'type', 'id', 'attributes' => [
'email', 'uuid', 'created_at', 'updated_at',
],
])
->assertJson(['type' => 'example',...]);
In the docs I can see this:
Http::fake([
'github.com/*' => Http::response(['foo' => 'bar'], 200, ['Headers']),
]);
How can I mock/fake the request to a 3rd party url and assert a good response? Thank you for any suggestions!
Upvotes: 3
Views: 18111
Reputation: 35180
As per the docs (and your question) you can pass an array to Http::fake()
to specify what response you would like for which requests i.e. the key
is the request url and the value is the mocked response.
Your test would be something like:
$user = factory(User::class)->create(['email' => '[email protected]']);
Http::fake([
'www.example.com/third-party-url' => Http::response([
'type' => 'example',
'id' => 'some id',
'attributes' => [
'email' => 'some email',
'uuid' => 'some uuid',
'created_at' => 'some created_at',
'updated_at' => 'some updated_at',
],
], 200),
]);
$this->actingAs($user, 'api')
->getJson('api/v1/my/endpoint/123456')
->assertStatus(200)
->assertJsonStructure([
'type',
'id',
'attributes' => [
'email',
'uuid',
'created_at',
'updated_at',
],
])
->assertJson(['type' => 'example', ...]);;
Upvotes: 11
Reputation: 81
You can use
use GuzzleHttp\Handler\MockHandler;
Your myFunction code will be something like
$mock = new MockHandler([
new Response(200, [], File::get(base_path('your-mock-response-success.json'))),
]);
$handler = HandlerStack::create($mock);
$client = new Client(['handler' => $handler]);
$mock = $this->mock(YourService::class);
$mock->shouldReceive('create')
->andReturn($client);
Upvotes: 1