Skip to content
Santekno.com | Level Up Your Engineering Skills
ID
📖 0%
02 Sep 2025 · 6 mnt baca ·Artikel 86 / 110
Go

86. Studi Kasus: Testing Layanan CRUD dengan gRPC

IH
Ihsan Arif
Penulis di Santekno · Backend Engineer

86. Studi Kasus: Testing Layanan CRUD dengan gRPC

Dewasa ini, pengembangan aplikasi skala besar cenderung mengadopsi arsitektur microservices serta protokol komunikasi yang efisien, seperti gRPC. Banyak perusahaan menjadikan gRPC pilihan utama karena performa tinggi dan schema-driven API menggunakan Protocol Buffers. Namun, tantangan terbesar yang kerap muncul adalah bagaimana melakukan pengujian (testing) dengan efektif, khususnya untuk layanan CRUD (Create, Read, Update, Delete).

Pada artikel ini, saya ingin mengajak Anda menyelami sebuah studi kasus nyata mengenai testing layanan CRUD berbasis gRPC. Saya akan membahas struktur layanan, strategi pengujian unit, integration testing, hingga automatisasi pengujian. Simulasi kode akan menggunakan bahasa Go (Golang) karena popularitasnya dalam ekosistem gRPC.


Latar Belakang Masalah

Bayangkan sebuah tim mengembangkan service BookService yang menawarkan operasi CRUD pada entitas Book. Layanan ini harus cepat, andal, dan mudah untuk diuji. Pengujian otomatis diperlukan demi memastikan perubahan kode tidak menimbulkan regresi. Tes juga harus mudah dijalankan, baik di lingkungan lokal maupun CI/CD pipeline.

Diagram Alur CRUD di BookService

MERMAID
flowchart TD
    C(Client) -->|CreateRequest| S(BookService)
    C(Client) -->|ReadRequest| S(BookService)
    C(Client) -->|UpdateRequest| S(BookService)
    C(Client) -->|DeleteRequest| S(BookService)
    subgraph S
      direction TB
      DB[(Database)]
    end
    S --> DB

Definisi Protobuf

Langkah pertama dalam pengembangan layanan gRPC adalah mendeskripsikan API dengan protobuf:

protobuf
 1syntax = "proto3";
 2
 3package book;
 4
 5service BookService {
 6    rpc CreateBook (Book) returns (BookId) {}
 7    rpc GetBook (BookId) returns (Book) {}
 8    rpc UpdateBook (Book) returns (Book) {}
 9    rpc DeleteBook (BookId) returns (Empty) {}
10}
11
12message Book {
13    string id = 1;
14    string title = 2;
15    string author = 3;
16}
17
18message BookId {
19    string id = 1;
20}
21
22message Empty {}

Dengan skema ini, struktur API jelas, mudah didokumentasi dan dikonsumsi oleh klien lintas bahasa.


Struktur Proyek Go

Mari simulasikan struktur direktori sederhana untuk BookService.

shell
1bookservice/
2  ├── proto/
3  │   └── book.proto
4  ├── main.go
5  ├── server.go
6  ├── repository.go
7  └── repository_test.go

Implementasi Server Sederhana

Bagian server akan menghandle request CRUD. Repository di-abstract agar memudahkan testing:

go
 1// repository.go
 2type Book struct {
 3    ID     string
 4    Title  string
 5    Author string
 6}
 7
 8type BookRepository interface {
 9    Create(book Book) (string, error)
10    Get(id string) (Book, error)
11    Update(book Book) error
12    Delete(id string) error
13}
14
15type InMemoryBookRepo struct {
16    books map[string]Book
17}
18
19func (r *InMemoryBookRepo) Create(book Book) (string, error) {
20    r.books[book.ID] = book
21    return book.ID, nil
22}
23
24func (r *InMemoryBookRepo) Get(id string) (Book, error) {
25    if book, ok := r.books[id]; ok {
26        return book, nil
27    }
28    return Book{}, errors.New("not found")
29}
30
31func (r *InMemoryBookRepo) Update(book Book) error {
32    if _, ok := r.books[book.ID]; ok {
33        r.books[book.ID] = book
34        return nil
35    }
36    return errors.New("not found")
37}
38
39func (r *InMemoryBookRepo) Delete(id string) error {
40    if _, ok := r.books[id]; ok {
41        delete(r.books, id)
42        return nil
43    }
44    return errors.New("not found")
45}

Pengujian Unit: Fokus pada Repository

Sebelum menguji service penuh, pengujian unit pada repository penting dilakukan. Tujuannya untuk memastikan logika dasar CRUD sudah benar, independen dari gRPC. Berikut contoh test case menggunakan testing package di Go:

go
 1// repository_test.go
 2func TestInMemoryBookRepo_CRUD(t *testing.T) {
 3    repo := &InMemoryBookRepo{books: map[string]Book{}}
 4    book := Book{ID: "1", Title: "Go in Action", Author: "John Doe"}
 5    
 6    // Test Create
 7    id, err := repo.Create(book)
 8    if err != nil || id != "1" {
 9        t.Errorf("Create failed, got id=%v, err=%v", id, err)
10    }
11
12    // Test Read
13    b, err := repo.Get("1")
14    if err != nil || b.Title != "Go in Action" {
15        t.Errorf("Get failed, got book=%v, err=%v", b, err)
16    }
17
18    // Test Update
19    book.Title = "Go Lang in Action"
20    err = repo.Update(book)
21    if err != nil {
22        t.Errorf("Update failed: %v", err)
23    }
24
25    // Test Delete
26    err = repo.Delete("1")
27    if err != nil {
28        t.Errorf("Delete failed: %v", err)
29    }
30}

Manfaat Pengujian Unit

  • Isolasi: Memastikan komponen repository berjalan seperti yang diharapkan, terlepas dari protokol komunikasi.
  • Kecepatan: Test berjalan sangat cepat.

Integration Testing dengan gRPC

Selanjutnya, kita perlu menguji apakah service server gRPC benar-benar meng-translate request menjadi operasi CRUD yang benar.

Setup Integration Test

  1. Spin up server gRPC dengan repository in-memory.
  2. Kirim request ke server menggunakan client gRPC secara langsung.
go
 1// integration_test.go (pseudo)
 2func TestBookServiceIntegration(t *testing.T) {
 3    // 1. Jalankan server (tanpa perlu listen di port production)
 4    lis := bufconn.Listen(1024 * 1024)
 5    s := grpc.NewServer()
 6    repo := &InMemoryBookRepo{books: map[string]Book{}}
 7    RegisterBookServiceServer(s, &BookServiceServer{repo: repo})
 8    go s.Serve(lis)
 9    defer s.Stop()
10
11    // 2. Set client dengan custom dial
12    ctx := context.Background()
13    conn, _ := grpc.DialContext(
14        ctx, "bufnet",
15        grpc.WithContextDialer(func(context.Context, string) (net.Conn, error) {
16            return lis.Dial()
17        }),
18        grpc.WithInsecure(),
19    )
20    defer conn.Close()
21    client := NewBookServiceClient(conn)
22
23    // 3. Proses uji integrasi end-to-end
24    resp, err := client.CreateBook(ctx, &Book{Id: "123", Title: "gRPC for Dummies", Author: "Jane"})
25    // 4. Assert validations
26    if err != nil || resp.Id != "123" {
27        t.Fatalf("Expected Id=123, got %v, err=%v", resp.Id, err)
28    }
29}

Tabel Hasil Pengujian Skenario CRUD

OperasiInputOutput / EkspetasiStatus
Createid=123, title=“gRPC for Dummies”Success, id=123Pass
Readid=123Book ditemukanPass
Updateid=123, title=“gRPC 101”Book diperbaruiPass
Deleteid=123Book dihapusPass
Readid=999 (belum ada)Error: not foundPass

Automasi Testing di CI/CD Pipeline

Testing service gRPC di atas bisa langsung diotomasi dalam pipeline CI-CD (misal dengan Github Actions atau Gitlab CI). Kunci utama keberhasilan: tidak ada dependency ke infrastruktur eksternal, servis bisa spin-up dan testing sendiri dengan dependency in-memory.

Tips Otomasi Testing:

  • Gunakan test double untuk resource eksternal (e.g. in-memory or mock).
  • Pastikan coverage test minimal untuk seluruh fitur CRUD.
  • Pisahkan test unit vs integration (misal dengan suffix _test.go).

Key Takeaways

  • gRPC sangat powerful untuk layanan high performance dan schema-first.
  • Testing CRUD wajib dilakukan di dua level: unit (logic) dan integration (antarmuka gRPC).
  • Strategy dengan in-memory repository memudahkan isolasi dan otomasi test di pipeline.
  • Test coverage tidak boleh hanya di operation “bahagia” (happy case), tapi juga kasus limit & error.

Kesimpulan

Testing layanan CRUD berbasis gRPC bisa dibuat sederhana dan powerful dengan strategi modularisasi komponen, penulisan test unit & integration yang sistematis, serta mengandalkan in-memory dependency. Dengan pendekatan ini error lebih cepat ditemukan, development velocity meningkat, serta codebase lebih tangguh menghadapi perubahan.

Secara praktis, model seperti ini mudah direplikasi untuk layanan microservice lain, dan membangun fondasi engineering excellence yang kuat di tim pengembang Anda.


Referensi:


Semoga studi kasus ini menambah insight Anda dalam membangun dan menguji layanan CRUD gRPC yang scalable dan reliable!

Artikel Terkait

💬 Komentar