testcontainers_modules/elasticmq/
mod.rs

1use testcontainers::{core::WaitFor, Image};
2
3const NAME: &str = "softwaremill/elasticmq";
4const TAG: &str = "1.5.2";
5
6/// Module to work with [`ElasticMQ`] inside of tests.
7///
8/// Starts an instance of ElasticMQ based on the official [`ElasticMQ docker image`].
9///
10/// ElasticMQ is a message queue system, offering an actor-based Scala and an SQS-compatible REST (query) interface.
11/// This module provides a local ElasticMQ instance for testing purposes, which is compatible with the AWS SQS API.
12/// The container exposes port `9324` by default.
13///
14/// # Example
15/// ```
16/// use testcontainers_modules::{elasticmq::ElasticMq, testcontainers::runners::AsyncRunner};
17///
18/// # async fn example() -> Result<(), Box<dyn std::error::Error + 'static>> {
19/// let elasticmq_instance = ElasticMq::default().start().await?;
20/// let host = elasticmq_instance.get_host().await?;
21/// let port = elasticmq_instance.get_host_port_ipv4(9324).await?;
22///
23/// // Use the SQS-compatible endpoint at http://{host}:{port}
24/// # Ok(())
25/// # }
26/// ```
27///
28/// [`ElasticMQ`]: https://github.com/softwaremill/elasticmq
29/// [`ElasticMQ docker image`]: https://hub.docker.com/r/softwaremill/elasticmq
30#[derive(Debug, Default, Clone)]
31pub struct ElasticMq {
32    /// (remove if there is another variable)
33    /// Field is included to prevent this struct to be a unit struct.
34    /// This allows extending functionality (and thus further variables) without breaking changes
35    _priv: (),
36}
37
38impl Image for ElasticMq {
39    fn name(&self) -> &str {
40        NAME
41    }
42
43    fn tag(&self) -> &str {
44        TAG
45    }
46
47    fn ready_conditions(&self) -> Vec<WaitFor> {
48        vec![WaitFor::message_on_stdout("Started SQS rest server")]
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use std::fmt::Display;
55
56    use aws_config::{meta::region::RegionProviderChain, BehaviorVersion};
57    use aws_sdk_sqs::{config::Credentials, Client};
58
59    use crate::{elasticmq::ElasticMq, testcontainers::runners::AsyncRunner};
60
61    #[tokio::test]
62    async fn sqs_list_queues() -> Result<(), Box<dyn std::error::Error + 'static>> {
63        let node = ElasticMq::default().start().await?;
64        let host_ip = node.get_host().await?;
65        let host_port = node.get_host_port_ipv4(9324).await?;
66        let client = build_sqs_client(host_ip, host_port).await;
67
68        let result = client.list_queues().send().await.unwrap();
69        // list should be empty
70        assert!(result.queue_urls.filter(|urls| !urls.is_empty()).is_none());
71        Ok(())
72    }
73
74    async fn build_sqs_client(host_ip: impl Display, host_port: u16) -> Client {
75        let endpoint_uri = format!("http://{host_ip}:{host_port}");
76        let region_provider = RegionProviderChain::default_provider().or_else("us-east-1");
77        let creds = Credentials::new("fakeKey", "fakeSecret", None, None, "test");
78
79        let shared_config = aws_config::defaults(BehaviorVersion::latest())
80            .region(region_provider)
81            .endpoint_url(endpoint_uri)
82            .credentials_provider(creds)
83            .load()
84            .await;
85
86        Client::new(&shared_config)
87    }
88}