Database casting helpers
use SavvyWombat\LaravelTestUtils\DBCast
DBCast::toJson
Use this casting helper when making assertions against the database (such as with
assertDatabaseHas
or assertDatabaseMissing
) to cast an array or json string
to an SQL JSON datatype.
$this->assertDatabaseHas('vehicles', [
'id' => 1,
'manufacturer' => 'Toyford',
'model' => 'Llama',
'attributes' => DBCast::toJson([
'color' => 'indigo green',
'engine' => '2 litres 4-cylinder',
'gearbox' => '6-speed manual',
'doors' => '5',
]),
]);
DBCast::toTimestamp
Use this casting helper to assert DateTime or Carbon instances against SQL timestamps in the database.
$trip = Trip::factory()->create();
Carbon::setTestNow("2020-10-20 10:15:43");
$response = $this->get('/start-trip');
$response->assertStatus(200)
->assertSee('Trip started');
$this->assertDatabaseHas('trips', [
'id' => $trip->id,
'trip_started_at' => DBCast::toTimestamp(Carbon::now()),
]);
Carbon::setTestNow();
Mock guzzle
This trait assumes that you are using Laravel's dependency injection to inject a Guzzle client into your code. Using this trait in a test case will inject a mock client in place of your application's default client, allowing you to test your code's reaction to predictable responses without actually connecting to the remote API.
namespace App\Http\Controllers;
use GuzzleHttp\Client;
use Illuminate\Http\Request;
class ContactController extends Controller
{
public function send(Request $request, Client $client)
{
// Validate ReCaptcha as part of a contact form send request
$response = $this->client->post(config('recaptcha.url'), [
'query' => [
'secret' => config('recaptcha.secret'),
'response' => $request->input(['g-recaptcha-token'], ''),
]
]);
if (json_decode($response->getBody())->success) {
redirect()->route('contact::success');
} else {
redirect()->route('contact::form')->withErrors(['g-recaptcha-token' => 'Please confirm you are a human!']);
}
}
namespace Tests\Feature;
use GuzzleHttp\Psr7\Response;
use SavvyWombat\LaravelTestUtils\MocksGuzzle;
use Tests\TestCase;
class MyTest extends TestCase
{
use MocksGuzzle;
/** @test */
public function it_reacts_appropriately_to_recaptcha_success()
{
$this->guzzle() // this is guzzle's MockHandler class
->append(new Response(200, [], json_encode(['success' => 'true'])));
$this->post('/some-url', ['message' => 'some message', 'g-recaptcha-token' => 'blah'])
->assertStatus(302)
->assertSessionHasNoErrors()
->assertRedirect('/success');
}
/** @test */
public function it_errors_on_recaptcha_failure()
{
$this->guzzle() // this is guzzle's MockHandler class
->append(new Response(200, [], json_encode(['success' => 'false'])));
$this->post('/some-url', ['message' => 'some message', 'g-recaptcha-token' => 'blah'])
->assertStatus(302)
->assertSessionHasErrors('g-recaptcha-token')
->assertRedirect('/some-url');
}
}
If your controller or other code under test needs to make more than one request to an API, you can chain responses to the guzzle handler:
$this->guzzle()
->append(new Response(200, [], json_encode(['invoices' => ['id' => '1245', 'id' => '1247']])))
->append(new Response(404));
Caveats
Currently, the guzzle mock doesn't assert or check anything regarding what requests you are making - it's just a simple way to test your code's reaction to a particular response without having to actually transmit a request to the remote API.