Pendahuluan
Go Fiber v3 adalah web framework minimalis yang memberikan performa tinggi dan struktur modular. Dalam pengembangan API modern, memastikan logika kritis berfungsi sebelum deployment sangat krusial agar kualitas tetap terjaga. Artikel ini mengulas strategi pengujian menyeluruh: mulai dari unit test service, pengujian handler HTTP berbasis table-driven, hingga mock database serta pengujian upload/import Excel. Tujuannya membantu engineer menyusun test cepat, stabil, dan mudah dirawat di pipeline CI.
Unit Test Service dengan Table-Driven
Unit test service menjadi langkah pertama memastikan business logic tertutup dengan baik. Format table-driven test menjaga struktur kasus tetap konsisten, memudahkan penambahan skenario baru, dan meminimalisir duplikasi kode.
func TestUserService_Create(t *testing.T) { t.Parallel()
cases := []struct {
name string
input CreateUserInput
repoFunc func(*mockUserRepo, CreateUserInput)
expectErr bool
}{
// tambahkan kasus valid, invalid, conflict, dll.
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
repo := newMockUserRepo(t)
tc.repoFunc(repo, tc.input)
svc := NewUserService(repo)
got, err := svc.Create(context.Background(), &tc.input)
if tc.expectErr {
require.Error(t, err)
return
}
require.NoError(t, err)
require.Equal(t, expectedUser, got)
})
}
}Pastikan setiap kasus menyetel repoFunc yang mereplikasi perilaku repository agar test tetap terisolasi dan deterministik. Table-driven memudahkan menambahkan skenario validasi input, konflik database, ataupun error yang disengaja tanpa mengubah kerangka utama test.
Pengujian Handler HTTP Fiber
Setelah service stabil, level berikutnya adalah pengujian HTTP handler. Fiber menyediakan app.Test(req) sehingga handler dapat diuji end-to-end dari routing, validasi payload, hingga respons JSON.
func TestRegisterHandler(t *testing.T) {
app := fiber.New()
handler := NewRegisterHandler(mockService)
app.Post("/register", handler.Handle)
payload := `{"email":"user@example.com","password":"secret"}`
req := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(payload))
req.Header.Set("Content-Type", "application/json")
res, _ := app.Test(req)
require.Equal(t, http.StatusCreated, res.StatusCode)
body, _ := io.ReadAll(res.Body)
require.JSONEq(t, `{"status":"ok","data":{"email":"user@example.com"}}`, string(body))
}Gunakan require.JSONEq agar pengujian tidak sensitif terhadap urutan field. Untuk memverifikasi validasi input, simulasi request tak lengkap:
func TestRegisterHandler_BadPayload(t *testing.T) {
app := fiber.New()
handler := NewRegisterHandler(mockService)
app.Post("/register", handler.Handle)
req := httptest.NewRequest(http.MethodPost, "/register", strings.NewReader(`{}`))
req.Header.Set("Content-Type", "application/json")
res, _ := app.Test(req)
require.Equal(t, http.StatusBadRequest, res.StatusCode)
body, _ := io.ReadAll(res.Body)
require.Contains(t, string(body), "email is required")
}Pastikan validator dijalankan di handler atau middleware yang sama dengan produksi agar hasil pengujian mencerminkan perilaku sebenarnya.
Mock Repository dan Database
Mocking repository penting agar unit test terpisah dari database nyata dan bisa menghasilkan error deterministik. Gunakan testify/mock atau interface kustom yang mendukung dependency injection.
type UserRepository interface {
Create(ctx context.Context, user *User) error
GetByEmail(ctx context.Context, email string) (*User, error)
}
type mockUserRepo struct {
mock.Mock
}
func (m *mockUserRepo) Create(ctx context.Context, user *User) error {
return m.Called(ctx, user).Error(0)
}Siapkan skenario untuk:
- Success case mencocokkan hasil dengan data input.
- Conflict entry memicu error dan memverifikasi handler mengembalikan status 409.
- Timeout/connection error memicu
context.DeadlineExceededdan ditransformasikan menjadi status 503.
Mock memungkinkan Anda menulis pengujian ini tanpa terhubung ke database sungguhan, sekaligus memaksa service menangani retry atau rollback sesuai kebutuhan.
Pengujian Upload/Import Excel
Testing file upload—terutama Excel—mengharuskan simulasi multipart request dan validasi parsing. Berikut langkah umum:
- Buat file Excel dummy yang disimpan di folder
testdata. Anda bisa menggunakan paket sepertiexcelizeuntuk generate sekali lalu commit. - Gunakan
multipart.NewWriteruntuk membangun request upload inklusif field lain sepertiuser_idataumetadata. - Handler menyimpan file sementara, memanggil parser dan worker atau service yang memproses data.
- Lengkapi test untuk error path, misalnya worker queue gagal enqueue.
Contoh test error worker enqueue:
func TestImportExcelHandler_WorkerEnqueueError(t *testing.T) {
app := fiber.New()
handler := NewImportHandler(mockWorkerAdapter)
app.Post("/import", handler.Handle)
payload := newMultipartPayload(t, "testdata/users.xlsx")
req := httptest.NewRequest(http.MethodPost, "/import", payload.Body)
req.Header.Set("Content-Type", payload.ContentType)
mockWorkerAdapter.On("Enqueue", mock.Anything).Return(errors.New("queue error"))
res, _ := app.Test(req)
require.Equal(t, http.StatusServiceUnavailable, res.StatusCode)
body, _ := io.ReadAll(res.Body)
require.Contains(t, string(body), "worker enqueue failed")
}Pastikan handler menangani penyimpanan file sementara dan membersihkan resource di akhir. Mock worker adapter memungkinkan Anda memverifikasi bahwa behavior enqueue error dikonversi ke respons yang sesuai tanpa menjalankan queue nyata.
Kesimpulan
Testing API Go Fiber v3 membutuhkan pendekatan berlapis: unit test service table-driven, pengujian handler HTTP menyeluruh, repository mocking, serta skenario upload/import file yang realistis. Dengan pola ini, tim engineering bisa membangun tuis yang stabil, mudah diperluas, dan memberikan kepercayaan tinggi sebelum setiap deployment.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!