For the complete documentation index, see llms.txt. This page is also available as Markdown.

Unit Testing

Unit testing adalah praktik menulis kode untuk menguji kode lainnya. Tujuannya adalah memastikan setiap unit (fungsi, method, atau struct) berperilaku sesuai yang diharapkan. Dalam konteks ini, yang menjadi fokus adalah coverage โ€” seberapa banyak cabang logika (branch) dan aturan bisnis yang teruji.

๐Ÿ“‚ Kode Lengkap Bab Ini: Seluruh kode yang dibahas di bab ini tersedia di GitHub:

๐Ÿ”— github.com/jacky-htg/workshop/tree/main/20-unit-testing

20.1 Mengapa Unit Testing Penting?

Manfaat
Penjelasan

Mendeteksi bug lebih awal

Menemukan error sebelum kode masuk ke production

Memudahkan refactoring

Jika kode diubah, test akan memastikan tidak ada yang rusak

Dokumentasi hidup

Test menunjukkan bagaimana seharusnya fungsi digunakan

Desain yang lebih baik

Kode yang sulit di-test biasanya menandakan desain yang buruk

20.2 Prinsip Unit Testing di Go

Aturan Emas:

  1. File test harus diakhiri dengan _test.go

  2. Nama fungsi test dimulai dengan Test

  3. Gunakan testing.T sebagai parameter

  4. Setiap test harus independen (tidak tergantung urutan eksekusi)

func TestNamaFungsi_Skenario(t *testing.T) {
    // Arrange (setup)
    // Act (execute)
    // Assert (verify)
}

20.3 Tools yang Digunakan

Tool
Kegunaan

testing

Package standar Go untuk unit testing

github.com/stretchr/testify

Assertions yang lebih ekspresif

github.com/DATA-DOG/go-sqlmock

Mock database untuk repository test

net/http/httptest

Mock HTTP server untuk handler test

20.4 Test Repository

Repository memiliki ketergantungan pada *sql.DB dan logger.Logger. Karena kita sudah menerapkan dependency injection, kita bisa dengan mudah mengganti dependency asli dengan mock.

Mock Logger

Buat logger kosong (no-op) untuk testing (mock/mockpkg/logger.go):

Mock Database dengan sqlmock

sqlmock memungkinkan kita mensimulasikan query database tanpa perlu database sungguhan.

Pola Umum Mocking:

  • ExpectQuery() โ†’ untuk QueryRowContext() atau QueryContext()

  • ExpectExec() โ†’ untuk ExecContext()

  • ExpectPrepare() โ†’ untuk PrepareContext()

Test untuk QueryRowContext (Create Role)

Buat file internal/repository/role_repository_test.go.

Test untuk QueryContext (List Roles)

Test untuk ExecContext (Update Role)

Menjalankan Test Repository

Untuk mengetes bisa digunakan perintah

20.5 Test Service

Service bergantung pada repository.RoleRepository (interface). Kita buat mock repository untuk mengontrol perilaku yang diinginkan.

Mock Repository untuk Service

buat file mock/mockrepo/role.go

Test Service Update

Kita akan membuat unit test untuk fungsi Update() yang komplektitas-nya sedang. Buat file internal/service/roles_test.go

20.6 Test Handler

Handler bergantung pada service.Roles (interface). Kita buat mock service dan gunakan httptest untuk mensimulasikan HTTP request.

Mock Service untuk Handler

Test Handler Update

Buat file internal/hanlder/role_handler_test.go

20.7 Menjalankan Semua Test

20.8 Best Practices Unit Testing

Praktik
Penjelasan

Satu skenario per test

Satu fungsi test hanya menguji satu skenario (success atau satu jenis error)

Nama test deskriptif

TestNamaFungsi_Skenario_Hasil โ†’ TestRoleRepository_Create_DuplicateKey_Error

Gunakan table-driven test

Untuk skenario yang mirip dengan input berbeda

Mock eksternal dependency

Database, API, file system harus di-mock

Test edge cases

Nilai kosong, limit, negative, dll

Contoh Table-Driven Test

Ringkasan Bab 20

Di bab ini kita telah belajar:

Komponen
Pendekatan Test
Tools

Repository

Mock database

sqlmock

Service

Mock repository

Custom mock struct

Handler

Mock service + HTTP mock

httptest

Manfaat yang kita peroleh:

  • โœ… Setiap fungsi memiliki test yang memverifikasi perilaku

  • โœ… Dependency eksternal (database) tidak perlu untuk testing

  • โœ… Coverage bisa diukur dan ditingkatkan

  • โœ… Refactoring kode lebih aman

Yang akan datang:

  • Unit testing menguji komponen secara terisolasi

  • Bab selanjutnya: API Testing โ€“ menguji endpoint secara end-to-end dengan database dan server sungguhan

Last updated