Membuat HTTP test untuk pengembangan API pada Laravel
Ada beberapa metode untuk melakukan otomasi pengujian dalam pengembangan Web. Pada Laravel, salah satu cara yang bisa digunakan untuk melakukan pengujian terhadap (REST) API, untuk memastikan fungsinya berjalan benar, bisa dengan menggunakan HTTP Tests.
HTTP Testing Controller
Ketika membuat controller dengan artisan disediakan opsi --test
yang bisa digunakan untuk membuat testing untuk setiap route yang akan di-handle oleh controller.
Contohnya membuat controller dengan command berikut :
php artisan make:controller BookController --test
Maka akan menghasilkan controller dan test case berikut :
Membuat Request HTTP
Untuk melakukan testing pada endpoint API, kita perlu mengakses route sesuai path dan http method-nya. Hal itu bisa dilakukan dengan memanggil http method dari test case class.
$response = $this->get(route('api.books.index'));
...
$response = $this->get(route('api.books.show', ['id' => $id]));
...
$response = $this->post(route('api.books.store'), $data);
...
$response = $this->put(route('api.books.update', ['id' => $id]), $data);
...
$response = $this->delete(route('api.books.destroy', ['id' => $id]));
Menyertakan HTTP Header
Ketika melakukan request, kita bisa menyertakan request header yang diinginkan dengan menggunakan withHeader
atau withHeaders
$response = $this->withHeader('Accept', 'application/json')
->get(route('api.books.index'));
...
$response = $this->withHeaders(['Accept' => 'application/json'])
->get(route('api.books.index'));
Model Factory
Karena API yang kita uji membutuhkan data, maka diperlukan sebuah cara untuk membuat data dummy menggunakan model factory. Pada API yang kita uji memiliki model dengan property sebagai berikut :
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'title',
'synopsis',
'author'
];
Maka kita bisa membuat model factory seperti berikut :
/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Book>
*/
class BookFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array<string, mixed>
*/
public function definition(): array
{
return [
'title' => fake()->text(20),
'synopsis' => fake()->text(150),
'author' => fake()->name()
];
}
}
Pada test case bisa dilakukan pemanggilan model factory seperti berikut :
$books = Book::factory(2)->create();
Otentifikasi (Authentication)
Untuk melakukan pengujian endpoint yang membutuhkan authentikasi, kita bisa menggunakan helper method actingAs
seperti berikut :
$user = User::factory()->create();
$response = $this->actingAs($user)
->withHeader('Accept', 'application/json')
->post(route('api.books.store'), $data);
In-Memory Database
Ketika melakukan pengujian yang terotomasi, disarankan untuk menggukaan in memori database. HTTP Tests, menggunakan phpunit dibalik layar, maka kita bisa melakukan konfigurasi penggunakan database untuk pengujian pada file phpunit.xml
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
Sertakan juga traits untuk melakukan refresh database pada setiap class test case, agar database migration selalu dijalankan setiap kali test case dijalankan.
use RefreshDatabase;
JSON Test Assertion
Pada contoh kali ini akan membuat test case untuk API data buku. assertion yang akan digunakan adalah sebagai berikut:
$response->assertStatus(/** HTTP Status Code **/);
..
$response->assertJsonStructure(/** Structure JSON **/);
...
$response->assertJson(/** more detailed JSON assertion **/);
Berikut adalah contoh dari test case yang bisa dibuat :
class BookControllerTest extends TestCase
{
use RefreshDatabase;
public function test_can_list_books(): void
{
$books = Book::factory(2)->create();
$response = $this->withHeader('Accept', 'application/json')
->get(route('api.books.index'));
$response->assertStatus(Response::HTTP_OK);
$response->assertJsonStructure([
'data' => [
'*' => [
'id',
'title',
'synopsis',
'author'
]
]
]);
$response->assertJson(
fn (AssertableJson $json) =>
$json->has(
'data',
fn (AssertableJson $json) =>
$json->first(
fn (AssertableJson $json) =>
$json->where('id', $books[0]->id)
->where('title', $books[0]->title)
->where('synopsis', $books[0]->synopsis)
->where('author', $books[0]->author)
)->etc()
)->etc()
);
}
public function test_can_create_book(): void
{
$user = User::factory()->create();
$data = [
'title' => 'Something Cool',
'synopsis' => 'Once upon a time...',
'author' => 'John Doe'
];
$response = $this->actingAs($user)
->withHeader('Accept', 'application/json')
->post(route('api.books.store'), $data);
$response->assertStatus(Response::HTTP_CREATED);
$response->assertJsonStructure([
'data' => [
'id',
'synopsis',
'author'
]
]);
$response->assertJson(
fn (AssertableJson $json) =>
$json->has(
'data',
fn (AssertableJson $json) =>
$json->where('title', $data['title'])
->where('synopsis', $data['synopsis'])
->where('author', $data['author'])
->etc()
)
);
}
}
Dan berikut adalah controller yang diuji :
class BookController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Resources\Json\AnonymousResourceCollection
*/
public function index(): AnonymousResourceCollection
{
$books = Book::query()->simplePaginate(10, [
'id',
'title',
'synopsis',
'author'
]);
return BookResource::collection($books);
}
/**
* Store a newly created resource in storage.
*
* @param \App\Http\Requests\BookRequest $request
*
* @return \App\Http\Resources\BookResource
*/
public function store(BookRequest $request): BookResource
{
$data = $request->validated();
$book = Book::query()->create($data);
return new BookResource($book);
}
}
Kata Penutup
Demikian contoh otomasi API testing yang bisa dilakukan dengan menggunakan HTTP Tests pada Laravel untuk melakukan pengujian API. Semoga tulisan kali ini bermanfaat. Sampai jumpa di tulisan selanjutnya. Salam.
Baca Lebih Lanjut