Pemrograman

16 Soft Delete dalam GORM: Panduan Lengkap dengan Unit Test

Pelajari cara menggunakan soft delete di GORM untuk menghapus data tanpa benar-benar menghapusnya. Panduan ini mencakup contoh kode, penjelasan, dan unit test menggunakan SQLMock.

Soft delete adalah fitur yang memungkinkan penghapusan data tanpa benar-benar menghapusnya dari database. GORM menyediakan mekanisme ini dengan menambahkan kolom DeletedAt secara otomatis dalam model.

1. Soft Delete

Contoh Kode

package main

import (
    "database/sql"
    "fmt"
    "testing"
    "github.com/DATA-DOG/go-sqlmock"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
    "gorm.io/gorm/clause"
)

type User struct {
    ID        uint `gorm:"primaryKey"`
    Name      string
    DeletedAt gorm.DeletedAt `gorm:"index"`
}

func softDeleteUser(db *gorm.DB, userID uint) error {
    result := db.Delete(&User{}, userID)
    return result.Error
}

Penjelasan Kode

  • Mendefinisikan model User dengan kolom DeletedAt, yang memungkinkan fitur soft delete.
  • Fungsi softDeleteUser akan menghapus user berdasarkan ID dengan metode Delete(), yang hanya menandai DeletedAt tanpa benar-benar menghapus data dari database.

Unit Test

func TestSoftDeleteUser(t *testing.T) {
    db, mock, _ := sqlmock.New()
    defer db.Close()
    gormDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: db}), &gorm.Config{})

    mock.ExpectExec("UPDATE users").WillReturnResult(sqlmock.NewResult(1, 1))

    err := softDeleteUser(gormDB, 1)
    if err != nil {
        t.Errorf("Error soft deleting user: %v", err)
    }
}

Penjelasan Kode Unit Test

  • Menggunakan SQLMock untuk meniru query yang dijalankan saat melakukan soft delete.
  • Melakukan mocking untuk query UPDATE users yang mengubah nilai DeletedAt.
  • Memastikan fungsi softDeleteUser berjalan tanpa error.

2. Menemukan Data yang Sudah Dihapus

Contoh Kode

func findDeletedUsers(db *gorm.DB) ([]User, error) {
    var users []User
    result := db.Unscoped().Where("deleted_at IS NOT NULL").Find(&users)
    return users, result.Error
}

Penjelasan Kode

  • Fungsi findDeletedUsers akan mencari data user yang telah dihapus.
  • Menggunakan Unscoped() agar query dapat mengakses data dengan deleted_at IS NOT NULL.

Unit Test

func TestFindDeletedUsers(t *testing.T) {
    db, mock, _ := sqlmock.New()
    defer db.Close()
    gormDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: db}), &gorm.Config{})

    rows := sqlmock.NewRows([]string{"id", "name", "deleted_at"}).
        AddRow(1, "Charlie", "2024-01-01")
    mock.ExpectQuery("SELECT * FROM users").WillReturnRows(rows)

    users, err := findDeletedUsers(gormDB)
    if err != nil || len(users) == 0 {
        t.Errorf("Failed to retrieve deleted users")
    }
}

Penjelasan Kode Unit Test

  • Membuat mock hasil query untuk mencari user yang memiliki deleted_at tidak null.
  • Menambahkan data mock berisi satu user yang dihapus.
  • Menguji apakah fungsi findDeletedUsers dapat mengambil data tersebut tanpa error.

3. Menghapus Permanen Data

Contoh Kode

func permanentlyDeleteUser(db *gorm.DB, userID uint) error {
    result := db.Unscoped().Delete(&User{}, userID)
    return result.Error
}

Penjelasan Kode

  • Fungsi permanentlyDeleteUser menggunakan Unscoped().Delete() untuk benar-benar menghapus data dari database.
  • Berbeda dengan soft delete, data yang dihapus dengan metode ini tidak bisa dikembalikan.

Unit Test

func TestPermanentlyDeleteUser(t *testing.T) {
    db, mock, _ := sqlmock.New()
    defer db.Close()
    gormDB, _ := gorm.Open(postgres.New(postgres.Config{Conn: db}), &gorm.Config{})

    mock.ExpectExec("DELETE FROM users").WillReturnResult(sqlmock.NewResult(1, 1))

    err := permanentlyDeleteUser(gormDB, 1)
    if err != nil {
        t.Errorf("Error permanently deleting user: %v", err)
    }
}

Penjelasan Kode Unit Test

  • Menggunakan SQLMock untuk mengekspektasikan query DELETE FROM users.
  • Memastikan fungsi permanentlyDeleteUser dijalankan tanpa error.

Kesimpulan

  • Soft delete hanya menandai data sebagai dihapus tanpa benar-benar menghapusnya.
  • Data yang sudah dihapus bisa ditemukan dengan Unscoped().Where("deleted_at IS NOT NULL").
  • Penghapusan permanen bisa dilakukan dengan Unscoped().Delete(), yang akan benar-benar menghapus data dari database.
comments powered by Disqus