Redis (Remote Dictionary Server) adalah database in-memory yang dirancang untuk menyimpan data dalam bentuk struktur data sederhana, seperti string, hash, list, set, dan sorted set. Redis umumnya digunakan untuk caching, message brokering, dan tugas-tugas yang memerlukan kecepatan tinggi karena seluruh data disimpan di RAM, sehingga memungkinkan akses data yang sangat cepat.
Redis dikembangkan oleh Salvatore Sanfilippo pada tahun 2009. Awalnya, Sanfilippo menciptakan Redis untuk mengatasi masalah kinerja pada startup-nya sendiri yang mengharuskannya menyimpan data sesi pengguna dalam waktu singkat dengan kecepatan tinggi. Setelah menyadari potensi dan permintaan terhadap sistem semacam ini, ia memutuskan untuk membuka kode Redis sebagai proyek open-source di bawah lisensi BSD.
Seiring waktu, Redis berkembang pesat dan menjadi populer dalam industri teknologi. Pada tahun 2015, Redis Labs (sekarang bernama Redis Inc.) mengambil alih pemeliharaan utama Redis, dan Salvatore Sanfilippo bergabung dengan Redis Labs sebagai kepala arsitek. Redis kini digunakan oleh berbagai perusahaan besar seperti Twitter, GitHub, dan Stack Overflow, terutama untuk caching, queue management, dan aplikasi real-time.
Kasus Umum Dimana Redis Menjadi Solusi
Redis sangat populer dalam industri teknologi karena kecepatannya yang tinggi dan fleksibilitasnya. Berikut beberapa kasus nyata di mana Redis digunakan sebagai solusi tepat:
- Caching untuk Aplikasi WebRedis sering digunakan untuk caching di aplikasi web dengan trafik tinggi seperti Twitter dan Instagram. Karena Redis menyimpan data di memori, ini memungkinkan akses data yang sangat cepat, mengurangi waktu muat halaman secara signifikan. Data yang sering diakses, seperti profil pengguna atau data sesi, bisa disimpan dalam Redis untuk mengurangi beban pada database utama.
- Real-time AnalyticsRedis cocok untuk aplikasi yang memerlukan analitik secara real-time, seperti analitik pada situs e-commerce yang memantau produk yang sering dilihat atau dibeli. Karena Redis memungkinkan operasi baca dan tulis yang sangat cepat, data interaksi pengguna dapat diproses dan dianalisis dalam waktu nyata untuk menampilkan rekomendasi produk atau promosi yang relevan.
- Peringkat LeaderboardDalam aplikasi seperti game atau platform pembelajaran, leaderboard (papan peringkat) sering kali membutuhkan akses dan pembaruan data secara real-time. Redis menyediakan struktur data
sorted set
yang sangat ideal untuk leaderboard karena memungkinkan penambahan, penghapusan, dan pengurutan elemen dengan cepat, menjadikannya solusi tepat untuk peringkat pengguna atau skor dalam aplikasi. - Message Queue (Antrian Pesan)Redis juga dapat digunakan sebagai message broker, di mana ia menyimpan dan mendistribusikan pesan di antara layanan yang berbeda. Banyak perusahaan menggunakan Redis untuk aplikasi komunikasi internal yang membutuhkan antrian pesan, seperti chat atau notifikasi. Struktur
list
dan dukungan untuk pub/sub (publish/subscribe) di Redis memungkinkan pengiriman pesan yang cepat dan efisien. - Manajemen SesiRedis digunakan secara luas untuk penyimpanan sesi dalam aplikasi web. Misalnya, platform seperti GitHub menggunakan Redis untuk menyimpan sesi pengguna sehingga pengguna tidak perlu login ulang secara terus-menerus. Dengan menyimpan sesi di Redis, aplikasi dapat melakukan autentikasi dengan cepat dan mengurangi beban pada database utama.
- Pencegahan Duplicate Data dan Rate LimitingRedis juga sering digunakan untuk mencegah pengulangan data dalam aplikasi seperti sistem pemungutan suara atau survei daring. Dengan memanfaatkan struktur
set
yang hanya menyimpan nilai unik, Redis dapat memastikan tidak ada data yang berulang. Selain itu, Redis banyak digunakan untuk rate limiting, seperti membatasi jumlah percobaan login atau akses API pada aplikasi, yang berguna untuk mencegah spam atau brute force attacks.
Redis menjadi solusi yang populer di berbagai kasus ini karena mampu menangani skenario yang memerlukan respons cepat, konsistensi data, dan pengolahan data secara efisien di dalam memori.
Mekanisme Untuk Data Persistence
Secara default, Redis adalah database in-memory, artinya data utama disimpan di RAM. Namun, Redis mendukung beberapa mekanisme untuk persistence agar data tetap aman jika Redis atau server mengalami restart atau crash. Berikut adalah beberapa cara Redis menangani persistence:
- RDB (Redis Database Backup)Redis membuat snapshot secara periodik dari database dan menyimpannya ke disk dalam bentuk file
.rdb
. Kita dapat mengatur seberapa sering snapshot ini dibuat, misalnya setiap 15 menit atau setiap kali jumlah perubahan mencapai batas tertentu. Metode ini hemat sumber daya karena Redis hanya melakukan penyimpanan ke disk dalam interval waktu yang ditentukan, tetapi bisa kehilangan data yang belum disimpan jika terjadi kegagalan. - AOF (Append-Only File)Redis juga menawarkan mekanisme Append-Only File (AOF), yang mencatat setiap operasi tulis yang dilakukan pada database. Redis menyimpan operasi ini dalam sebuah file di disk sehingga bisa memulihkan data dengan menjalankan kembali operasi tersebut jika terjadi kegagalan. AOF lebih aman dari segi persistence karena memperbarui file setiap kali ada perubahan data, tetapi cenderung lebih lambat dibandingkan RDB.
- Kombinasi RDB dan AOFRedis mendukung penggunaan kedua metode ini secara bersamaan, sehingga pengguna dapat mengambil keuntungan dari kinerja cepat RDB dan keandalan AOF. Saat melakukan pemulihan data, Redis akan memilih metode yang lebih cepat (biasanya AOF) agar proses pemulihan lebih efisien.
- Snapshotting Manual atau Pemberhentian PersistenceRedis juga memungkinkan Kita untuk menonaktifkan semua persistence dan hanya menyimpan data di memori. Ini bermanfaat untuk kasus di mana data bisa diambil ulang dari sumber lain jika Redis restart atau crash, tetapi ini berarti data akan hilang ketika Redis dimatikan.
Dengan adanya opsi-opsi ini, Redis bisa dikonfigurasi untuk menjaga data tetap persisten di disk, meskipun sifat aslinya adalah in-memory.
Case dimana Penggunaan Redis Dianggap Kurang Tepat
Redis sangat cepat dan fleksibel, tetapi ada beberapa jenis kasus di mana Redis bukan pilihan yang tepat atau tidak optimal. Berikut adalah beberapa contoh kasus di mana penggunaan Redis kurang ideal:
- Penyimpanan Data yang Sangat BesarKarena Redis adalah in-memory database, semua data utama disimpan di RAM. Ini berarti biaya bisa menjadi sangat tinggi jika digunakan untuk menyimpan data dalam jumlah besar, seperti data historis atau arsip besar yang jarang diakses. Untuk penyimpanan data dalam jumlah besar yang jarang digunakan, database berbasis disk seperti PostgreSQL, MySQL, atau bahkan solusi NoSQL berbasis disk seperti MongoDB atau Cassandra lebih cocok.
- Penyimpanan Data yang Memerlukan Konsistensi TransaksionalRedis tidak mendukung transaksi yang kompleks seperti multi-document transactions atau ACID (Atomicity, Consistency, Isolation, Durability) dengan cara yang sama seperti database relasional. Jika aplikasi memerlukan jaminan transaksi dan konsistensi data yang tinggi (misalnya dalam sistem keuangan atau aplikasi e-commerce dengan alur transaksi yang rumit), database relasional seperti PostgreSQL atau MySQL lebih cocok.
- Analisis Data yang Berat atau Query KompleksRedis tidak mendukung query kompleks, joins, atau analisis data yang berat. Redis memang menawarkan operasi dasar seperti pencarian dan pengurutan, tetapi untuk analisis data yang kompleks (misalnya data mining atau analisis multi-dimensi) dan joins, database analitik seperti PostgreSQL, Apache Cassandra, atau bahkan data warehouse seperti Google BigQuery atau Amazon Redshift lebih tepat.
- Penyimpanan Data Berumur Panjang atau Data HistorisRedis kurang cocok untuk menyimpan data historis atau archival yang perlu disimpan dalam jangka panjang, terutama jika data tersebut jarang diakses. Redis lebih tepat untuk data yang sering diakses, seperti cache atau data real-time. Untuk data historis yang besar dan jarang diakses, penyimpanan berbasis disk atau cold storage seperti Amazon S3 lebih ekonomis.
- Aplikasi yang Memerlukan Pemulihan Data yang LengkapMeskipun Redis mendukung persistence dengan RDB dan AOF, mekanisme ini tidak dirancang untuk pemulihan data yang sepenuhnya aman seperti yang ditawarkan oleh database relasional atau database yang mendukung replikasi dan pemulihan data penuh. Misalnya, jika aplikasi membutuhkan replikasi otomatis, failover, dan backup yang lengkap dan sangat andal, database relasional atau database yang dirancang khusus untuk keandalan seperti PostgreSQL atau MongoDB lebih sesuai.
- Aplikasi dengan Skema Data KompleksRedis lebih baik digunakan untuk skema data yang sederhana dan tidak berstruktur kompleks. Jika data memiliki struktur kompleks atau bergantung pada relasi antar data yang rumit, database berbasis relasional yang mendukung relasi antar tabel dan skema kompleks lebih ideal. Redis tidak memiliki kemampuan schema management dan foreign keys, sehingga sulit mengatur data kompleks dengan Redis.
Dalam kasus-kasus ini, Redis tidak optimal dan menggunakan solusi yang lebih sesuai dapat menghemat sumber daya dan meningkatkan keandalan aplikasi. Redis sangat efektif sebagai cache, message broker, atau solusi penyimpanan data cepat, tetapi kurang ideal untuk penyimpanan data kompleks, besar, atau yang membutuhkan tingkat konsistensi dan keandalan tinggi.
Redis pada proyek Spring Boot berbasis Maven
Menambahkan dukungan Redis pada proyek Spring Boot berbasis Maven yang sudah ada cukup mudah. Berikut langkah-langkah yang bisa diikuti:
1. Tambahkan Dependency Redis di pom.xml
Pertama, tambahkan dependency Redis Spring Boot di file pom.xml
untuk mengintegrasikan Redis ke dalam proyek:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Dependency ini akan menambahkan Spring Data Redis dan semua dependensi yang dibutuhkan untuk mengakses Redis.
2. Konfigurasi Koneksi Redis di application.properties
atau application.yml
Selanjutnya, konfigurasi koneksi ke Redis di file application.properties
atau application.yml
sesuai dengan pengaturan server Redis. Berikut contoh pengaturan dasarnya:
Jika menggunakan application.properties
spring.data.redis.host=localhost
spring.data.redis.port=6379
spring.data.redis.password= # Jika tidak ada password, hilangkan baris ini
Catatan: Jika menggunakan Redis yang dikelola secara lokal, biarkan host ke localhost
dan port ke 6379
. Untuk server Redis yang di-host, masukkan detail server yang sesuai.
3. Buat RedisTemplate
untuk Interaksi dengan Redis
Selanjutnya, buat RedisTemplate
untuk membantu aplikasi berinteraksi dengan Redis. Tambahkan konfigurasi ini di kelas konfigurasi Spring Boot (misalnya, RedisConfig.java
):
package com.mhyusuf.yboilerplate.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// Set serializer untuk key dan value
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer()); // Bisa disesuaikan dengan jenis data yang disimpan
return template;
}
}
RedisTemplate
ini memungkinkan kita untuk melakukan operasi CRUD pada Redis. Serializer disesuaikan dengan tipe data yang digunakan; di sini StringRedisSerializer
digunakan untuk contoh sederhana.
4. Gunakan RedisTemplate dalam Kode Aplikasi
Kita sekarang dapat menggunakan RedisTemplate
di service atau repository untuk berinteraksi dengan Redis. Misalnya, buat kelas RedisService
untuk menyimpan dan mengambil data:
package com.mhyusuf.yboilerplate.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
@Service
public class RedisService {
private final RedisTemplate<String, Object> redisTemplate;
@Autowired
public RedisService(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void saveData(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String getData(String key) {
return (String) redisTemplate.opsForValue().get(key);
}
}
Di sini, saveData
digunakan untuk menyimpan data dengan pasangan key-value
, sementara getData
akan mengambil data berdasarkan key
.
5. Nyalakan Service Redis di Docker
Buat Redis Container |
Redis Container telah berjalan |
6. Jalankan dan Uji Proyek
Sekarang proyek Spring Boot Anda sudah memiliki dukungan Redis. Jalankan aplikasi dan coba gunakan RedisService
dalam kode aplikasi Anda atau pada unit test untuk memastikan integrasi Redis bekerja dengan benar.
Jika Redis berjalan di mesin lokal, Anda bisa memantau data yang masuk melalui command line Redis.
Kemudian, gunakan perintah seperti GET <key>
untuk memeriksa apakah data sudah berhasil disimpan di Redis.
Redis Telah Berjalan dan Spring boot bisa mengaksesnya |
Mermbuat REST APIs Sederhana Untuk Data dengan Redis
Selanjutnya adalah contoh REST API sederhana dengan operasi CRUD yang memanfaatkan Redis pada proyek Spring Boot yang sudah kita buat di langkah-langkah sebelumnya.
1. Tambahkan RedisController
untuk Endpoints CRUD
Buat kelas RedisController
yang akan menjadi REST controller untuk menangani permintaan CRUD.
package com.mhyusuf.yboilerplate.controller;
import com.mhyusuf.yboilerplate.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@RestController
@RequestMapping("/api/redis")
public class RedisController {
private final RedisService redisService;
@Autowired
public RedisController(RedisService redisService) {
this.redisService = redisService;
}
// Create or Update data
@PostMapping("/{key}")
public ResponseEntity<String> createOrUpdateData(@PathVariable String key, @RequestBody String value) {
redisService.saveData(key, value);
return new ResponseEntity<>("Data saved successfully", HttpStatus.OK);
}
// Read data
@GetMapping("/{key}")
public ResponseEntity<String> getData(@PathVariable String key) {
String value = redisService.getData(key);
if (value != null) {
return new ResponseEntity<>(value, HttpStatus.OK);
} else {
return new ResponseEntity<>("Data not found", HttpStatus.NOT_FOUND);
}
}
// Delete data
@DeleteMapping("/{key}")
public ResponseEntity<String> deleteData(@PathVariable String key) {
boolean deleted = redisService.deleteData(key);
if (deleted) {
return new ResponseEntity<>("Data deleted successfully", HttpStatus.OK);
} else {
return new ResponseEntity<>("Data not found", HttpStatus.NOT_FOUND);
}
}
}
2. Modifikasi RedisService
untuk Menyertakan Metode Delete dan Find All
Perbarui RedisService
untuk mendukung operasi penghapusan dan mendapatkan semua data:
package com.mhyusuf.yboilerplate.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class RedisService {
private final RedisTemplate<String, Object> redisTemplate;
@Autowired
public RedisService(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
public void saveData(String key, String value) {
redisTemplate.opsForValue().set(key, value);
}
public String getData(String key) {
return (String) redisTemplate.opsForValue().get(key);
}
public boolean deleteData(String key) {
return Boolean.TRUE.equals(redisTemplate.delete(key));
}
public Set<String> getAllKeys() {
return redisTemplate.keys("*");
}
}
3. Tambahkan Endpoint untuk Mendapatkan Semua Data (Opsional)
Tambahkan endpoint di RedisController
untuk mendapatkan semua data yang ada di Redis:
// Get all keys
@GetMapping("/all")
public ResponseEntity<Set<String>> getAllKeys() {
Set<String> keys = redisService.getAllKeys();
return new ResponseEntity<>(keys, HttpStatus.OK);
}
4. Hasil Akhir: Kumpulan Endpoint CRUD
Berikut adalah daftar endpoint yang sekarang tersedia di RedisController
:
- Create/Update Data:
POST /api/redis/{key}
– Menyimpan data dengankey
danvalue
yang diberikan dalam request body. - Read Data:
GET /api/redis/{key}
– Mengambil data berdasarkankey
. - Delete Data:
DELETE /api/redis/{key}
– Menghapus data berdasarkankey
. - Get All Keys:
GET /api/redis/all
– Mengambil semuakey
yang ada di Redis (opsional).
5. Testing API via Curl
Jalankan aplikasi Spring Boot dan gunakan aplikasi seperti Postman atau curl
untuk menguji API:
5.1. Contoh Create/Update Data
5.2. Contoh Get Data
5.3. Contoh Delete Data
5.4. Contoh Get All Keys
Dengan konfigurasi ini, API sederhana untuk CRUD data di Redis telah berhasil diimplementasikan pada proyek Spring Boot.
6. Testing API via Unit Test
Berikut adalah contoh unit test lengkap yang menguji fungsionalitas CRUD Redis pada Spring Boot. Kita akan menambahkan pengujian untuk RedisService
dan RedisController
.
1. Tambahkan Dependencies untuk Pengujian di pom.xml
Pastikan dependencies untuk pengujian, seperti JUnit dan Spring Boot Test, sudah ada di pom.xml
:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
2. Unit Test untuk RedisService
Buat kelas pengujian RedisServiceTest
untuk menguji setiap fungsi CRUD di RedisService
:
package com.mhyusuf.yboilerplate;
import com.mhyusuf.yboilerplate.service.RedisService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.Collections;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
class RedisServiceTest {
@Mock
private RedisTemplate<String, Object> redisTemplate;
@Mock
private ValueOperations<String, Object> valueOperations;
@InjectMocks
private RedisService redisService;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
when(redisTemplate.opsForValue()).thenReturn(valueOperations);
}
@Test
void testSaveData() {
String key = "testKey";
String value = "testValue";
redisService.saveData(key, value);
verify(valueOperations, times(1)).set(key, value);
}
@Test
void testGetData() {
String key = "testKey";
String value = "testValue";
when(valueOperations.get(key)).thenReturn(value);
String result = redisService.getData(key);
assertEquals(value, result);
verify(valueOperations, times(1)).get(key);
}
@Test
void testDeleteData() {
String key = "testKey";
when(redisTemplate.delete(key)).thenReturn(true);
boolean result = redisService.deleteData(key);
assertTrue(result);
verify(redisTemplate, times(1)).delete(key);
}
@Test
void testGetAllKeys() {
Set<String> keys = Collections.singleton("testKey");
when(redisTemplate.keys("*")).thenReturn(keys);
Set<String> result = redisService.getAllKeys();
assertEquals(keys, result);
verify(redisTemplate, times(1)).keys("*");
}
}
3. Unit Test untuk RedisController
Buat kelas pengujian RedisControllerTest
untuk menguji setiap endpoint di RedisController
menggunakan MockMvc:
package com.mhyusuf.yboilerplate;
import com.mhyusuf.yboilerplate.controller.RedisController;
import com.mhyusuf.yboilerplate.service.RedisService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Collections;
import java.util.Set;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(RedisController.class)
class RedisControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private RedisService redisService; // Gunakan @MockBean untuk RedisService
@InjectMocks
private RedisController redisController;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void testCreateOrUpdateData() throws Exception {
String key = "testKey";
String value = "testValue";
doNothing().when(redisService).saveData(key, value);
mockMvc.perform(post("/api/redis/{key}", key)
.content(value)
.contentType(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().string("Data saved successfully"));
}
@Test
void testGetData() throws Exception {
String key = "testKey";
String value = "testValue";
when(redisService.getData(key)).thenReturn(value);
mockMvc.perform(get("/api/redis/{key}", key))
.andExpect(status().isOk())
.andExpect(content().string(value));
}
@Test
void testGetData_NotFound() throws Exception {
String key = "unknownKey";
when(redisService.getData(key)).thenReturn(null);
mockMvc.perform(get("/api/redis/{key}", key))
.andExpect(status().isNotFound())
.andExpect(content().string("Data not found"));
}
@Test
void testDeleteData() throws Exception {
String key = "testKey";
when(redisService.deleteData(key)).thenReturn(true);
mockMvc.perform(delete("/api/redis/{key}", key))
.andExpect(status().isOk())
.andExpect(content().string("Data deleted successfully"));
}
@Test
void testDeleteData_NotFound() throws Exception {
String key = "unknownKey";
when(redisService.deleteData(key)).thenReturn(false);
mockMvc.perform(delete("/api/redis/{key}", key))
.andExpect(status().isNotFound())
.andExpect(content().string("Data not found"));
}
@Test
void testGetAllKeys() throws Exception {
Set<String> keys = Collections.singleton("testKey");
when(redisService.getAllKeys()).thenReturn(keys);
mockMvc.perform(get("/api/redis/all"))
.andExpect(status().isOk())
.andExpect(jsonPath("$[0]").value("testKey"));
}
}
4. Menjalankan Unit Test
Untuk menjalankan semua pengujian, gunakan perintah berikut di IntelliJ IDEA.
Contoh Konfigurasi Run Config Testing |
Service Testing Berhasil Pada Service |
Service Testing Berhasil Pada Controller |
Kode di atas akan menguji semua fungsionalitas CRUD dari
RedisService
dan RedisController
. Test ini memastikan bahwa setiap operasi berjalan sesuai yang diharapkan, serta memberikan feedback jika ada perubahan yang mempengaruhi fungsi-fungsi tersebut.
Comments
Post a Comment