Handling Large Payload for Testing API
October 22, 2021In this example, I am using Laravel for backend and Pest PHP for testing. This is the sample route and payload:
Route::post('submit', function(\Illuminate\Http\Request $request){
ray($request->all());
})->name('submit');
{
"first_name": "Lloric",
"last_name": "garcia",
"hobbies": [
"programming",
"gaming"
],
"products": [
{
"id": "p1",
"quantity": 1
},
{
"id": "p2",
"quantity": 2
}
]
}
Here is the typical API test suite:
it('submit to api', function(){
\Pest\Laravel\post(route('submit'),[
'first_name' => 'Lloric',
'last_name' => 'garcia',
'hobbies' => [
'programming',
'gaming',
],
'products' => [
[
'id' => 'p1',
'quantity' => 1
],
[
'id' => 'p2',
'quantity' => 2
]
]
])
->assertValid();
});
Result in ray debugger
Now, let us assume that the example above has large API payload. Repeating that payload multiple times is a tiresome task therefore we will create a reusable function to make this code maintainable.
For this use case, we will make a class called MySubmitPayloadTestFactory. (note: This is what I learned from Spatie Testing Laravel Course. Here is the reference episode to learn more.)
namespace Tests\Factories;
use Illuminate\Testing\TestResponse;
use function Pest\Laravel\post;
final class MySubmitPayloadTestFactory
{
// this is better, when dealing with Model
private string $firstName;
private string $lastName;
/** @var array */
private array $hobbies = [];
/** @var array > */
private array $product = [];
private function __construct()
{
}
public static function make(): self
{
return new self();
}
public function firstName(string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
public function lastName(string $lastName): self
{
$this->lastName = $lastName;
return $this;
}
public function addHobbies(string $hobby): self
{
$this->hobbies[] = $hobby;
return $this;
}
public function addProduct(string $product, int $quantity = 1): self
{
$this->product[] = [
'id' => $product,
'quantity' => $quantity,
];
return $this;
}
public function runPost(): TestResponse
{
return post(route('submit'), $this->generatePayload());
}
private function generatePayload(): array
{
return [
'first_name' => $this->firstName,
'last_name' => $this->lastName,
'hobbies' => $this->hobbies,
'products' => $this->product,
];
}
}
This is the updated test suite using the factory that we made:
it('submit to api v2', function () {
\Tests\Factories\MySubmitPayloadTestFactory::make()
->firstName('Lloric')
->lastName('garcia')
->addHobbies('programming')
->addHobbies('gaming')
->addProduct('p1')
->addProduct('p2', 2)
->runPost()
->assertValid();
});
Here is the before and after test suite:
it('submit to api', function () {
\Pest\Laravel\post(route('submit'), [
'first_name' => 'Lloric',
'last_name' => 'garcia',
'hobbies' => [
'programming',
'gaming',
],
'products' => [
[
'id' => 'p1',
'quantity' => 1,
],
[
'id' => 'p2',
'quantity' => 2,
],
],
])
->assertValid();
});
it('submit to api v2', function () {
\Tests\Factories\MySubmitPayloadTestFactory::make()
->firstName('Lloric')
->lastName('garcia')
->addHobbies('programming')
->addHobbies('gaming')
->addProduct('p1')
->addProduct('p2', 2)
->runPost()
->assertValid();
});
Good luck! Tweet me and share with me what you’ve been able to create!