testcontainers_modules/redis/stack.rs
1use testcontainers::{core::WaitFor, Image};
2
3const NAME: &str = "redis/redis-stack-server";
4const TAG: &str = "7.2.0-v8";
5
6/// Module to work with [`Redis Stack`] inside of tests.
7///
8/// Starts an instance of Redis Stack based on the official [`Redis Stack docker image`].
9///
10/// By default Redis is exposed on Port 6379 ([`REDIS_PORT`]) and has no access control. Please refer to the [`Redis reference guide`] for more informations on how to interact with the API.
11///
12/// # Example
13/// ```
14/// use redis::JsonCommands;
15/// use serde_json::json;
16/// use testcontainers_modules::{testcontainers::runners::SyncRunner, redis::{RedisStack, REDIS_PORT}};
17///
18/// let redis_instance = RedisStack::default().start().unwrap();
19/// let host_ip = redis_instance.get_host().unwrap();
20/// let host_port = redis_instance.get_host_port_ipv4(REDIS_PORT).unwrap();
21///
22/// let url = format!("redis://{host_ip}:{host_port}");
23/// let client = redis::Client::open(url.as_ref()).unwrap();
24/// let mut con = client.get_connection().unwrap();
25///
26/// con.json_set::<_,_,_,()>("my_key", "$", &json!({ "number": 42 })).unwrap();
27/// let result: String = con.json_get("my_key", "$..number").unwrap();
28/// ```
29///
30/// [`Redis Stack`]: https://redis.io/docs/about/about-stack/
31/// [`Redis Stack docker image`]: https://hub.docker.com/r/redis/redis-stack-server
32/// [`Redis reference guide`]: https://redis.io/docs/interact/
33/// [`REDIS_PORT`]: super::REDIS_PORT
34#[derive(Debug, Default, Clone)]
35pub struct RedisStack {
36 /// (remove if there is another variable)
37 /// Field is included to prevent this struct to be a unit struct.
38 /// This allows extending functionality (and thus further variables) without breaking changes
39 _priv: (),
40}
41
42impl Image for RedisStack {
43 fn name(&self) -> &str {
44 NAME
45 }
46
47 fn tag(&self) -> &str {
48 TAG
49 }
50
51 fn ready_conditions(&self) -> Vec<WaitFor> {
52 vec![WaitFor::message_on_stdout("Ready to accept connections")]
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use redis::JsonCommands;
59 use serde_json::json;
60
61 use crate::{
62 redis::{RedisStack, REDIS_PORT},
63 testcontainers::runners::SyncRunner,
64 };
65
66 #[test]
67 fn redis_fetch_an_integer_in_json() -> Result<(), Box<dyn std::error::Error + 'static>> {
68 let _ = pretty_env_logger::try_init();
69 let node = RedisStack::default().start()?;
70 let host_ip = node.get_host()?;
71 let host_port = node.get_host_port_ipv4(REDIS_PORT)?;
72 let url = format!("redis://{host_ip}:{host_port}");
73
74 let client = redis::Client::open(url.as_ref()).unwrap();
75 let mut con = client.get_connection().unwrap();
76
77 assert_eq!(
78 con.json_set("my_key", "$", &json!({ "number": 42 })),
79 Ok(true)
80 );
81 let result: String = con.json_get("my_key", "$..number").unwrap();
82 assert_eq!("[42]", result);
83 Ok(())
84 }
85}