Amazon SQS
Overview
The cloudstub-sqs module mocks Amazon Simple Queue Service. Its operation set is generated from the
AWS SQS Smithy model; AWS SDK v2 (≥ 2.20) drives it with the JSON / X-Amz-Target protocol.
The core queue and message operations are state-backed: a message sent through SendMessage is
returned by a later ReceiveMessage, survives a restart when a persistent store directory is
configured, and is visible through the REST API. The remaining operations are
registered from the model and return well-formed but stateless placeholder responses.
See Supported operations for the full list.
Standalone usage
Start the standalone server with the SQS module enabled (it is auto-downloaded if not already in the plugin directory):
Applications talk to it through the AWS SDK by pointing the client's endpoint at the mock port
(http://localhost:4566) — see the Test example for an SqsClient setup and
Standalone Mode for the full configuration.
To inspect and drive queue state from the terminal, use the CLI (clb), or call the
REST API on the API port (4567) directly — for example with curl. Parameters
are passed as query-string values. Send a message and receive it back:
$ clb sqs send-message --queue orders --body hello
{
"md5OfBody" : "5d41402abc4b2a76b9719d911017c592",
"messageId" : "7568e4c5-4484-4291-a44b-e648b8c47a26"
}
$ clb sqs receive-message --queue orders
{
"messages" : [ {
"body" : "hello",
"messageId" : "7568e4c5-4484-4291-a44b-e648b8c47a26",
"receiptHandle" : "7568e4c5-4484-4291-a44b-e648b8c47a26"
} ]
}
$ curl -s -X POST "http://localhost:4567/api/sqs/send-message?queue=orders&body=hello"
{"md5OfBody":"5d41402abc4b2a76b9719d911017c592","messageId":"7568e4c5-4484-4291-a44b-e648b8c47a26"}
$ curl -s "http://localhost:4567/api/sqs/receive-message?queue=orders"
{"messages":[{"body":"hello","messageId":"7568e4c5-4484-4291-a44b-e648b8c47a26","receiptHandle":"7568e4c5-4484-4291-a44b-e648b8c47a26"}]}
The REST API and the SDK share the same state store, so a message your application sends through the
SDK is returned by GET /api/sqs/receive-message, and vice versa. See
REST API access for the full route set.
Test example
In embedded mode, add cloudstub-sqs (see Getting Started) and exercise the
service end to end with CloudStubExtension:
import io.cloudstub.junit.CloudStubExtension;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import software.amazon.awssdk.auth.credentials.AnonymousCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sqs.SqsClient;
import software.amazon.awssdk.services.sqs.model.Message;
import java.net.URI;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(CloudStubExtension.class)
class SqsRoundTripTest {
@Test
void messageSentIsReceived() {
SqsClient sqs = SqsClient.builder()
.endpointOverride(URI.create(System.getProperty("aws.endpoint-url")))
.credentialsProvider(AnonymousCredentialsProvider.create())
.region(Region.US_EAST_1)
.build();
String queueUrl = sqs.createQueue(b -> b.queueName("orders")).queueUrl();
sqs.sendMessage(b -> b.queueUrl(queueUrl).messageBody("hello"));
List<Message> messages = sqs.receiveMessage(b -> b.queueUrl(queueUrl)).messages();
assertEquals(1, messages.size());
assertEquals("hello", messages.get(0).body());
}
}
REST API access
The module exposes a REST API under /api/sqs/…. These routes read and write the same
state as the AWS-protocol stubs — a message sent with the SDK is returned by
GET /api/sqs/receive-message, and vice versa. Parameters are passed as query-string values (e.g.
POST /api/sqs/send-message?queue=orders&body=hello).
| Route | Parameters | Description |
|---|---|---|
GET /api/sqs/list-queues |
— | List queues |
POST /api/sqs/send-message |
queue, body |
Send a message |
GET /api/sqs/receive-message |
queue |
Receive messages |
POST /api/sqs/purge-queue |
queue |
Purge all messages |
Supported operations
State-backed operations return live data from the shared state store:
| Operation | Behavior |
|---|---|
CreateQueue |
Records the queue; returns its URL |
GetQueueUrl |
Returns the URL for a queue name |
SendMessage |
Stores the message body; returns MessageId and MD5OfMessageBody |
ReceiveMessage |
Returns stored messages (honors MaxNumberOfMessages) |
DeleteMessage |
Removes a message by receipt handle |
DeleteQueue |
Removes the queue and its messages |
ListQueues |
Returns the URLs of all created queues |
GetQueueAttributes |
Returns attributes, including the live ApproximateNumberOfMessages |
The remaining operations are registered and return well-formed but stateless placeholder responses;
they do not read or mutate state: AddPermission, CancelMessageMoveTask, ChangeMessageVisibility,
ChangeMessageVisibilityBatch, DeleteMessageBatch, ListDeadLetterSourceQueues,
ListMessageMoveTasks, ListQueueTags, PurgeQueue, RemovePermission, SendMessageBatch,
SetQueueAttributes, StartMessageMoveTask, TagQueue, UntagQueue.
To purge a queue against state, use the POST /api/sqs/purge-queue REST route (see
REST API access); the AWS-protocol PurgeQueue operation is a placeholder and
does not clear messages.
Limitations
- Visibility timeout is not enforced — a received message stays visible until it is explicitly
deleted (no in-flight tracking or
ApproximateNumberOfMessagesNotVisibleaccounting). - FIFO queues are treated like standard queues — the
.fifoname andFifoQueueattribute are accepted but no deduplication or ordering is applied. - Dead-letter queues and message-move tasks are placeholders — no redrive is performed.
- Batch operations (
SendMessageBatch,DeleteMessageBatch,ChangeMessageVisibilityBatch) are placeholders and do not mutate state. - Queue permissions and tagging are placeholders.
SetQueueAttributesis a placeholder; queue attributes returned byGetQueueAttributesare fixed defaults (plus the live message count) and cannot be changed.- Message attributes, system attributes, and delay seconds are not stored or returned.
- The SQS Query API (queue URLs as HTTP endpoints with
?Action=…) is not supported; CloudStub serves SQS over the JSON /X-Amz-Targetprotocol only.
See also: Troubleshooting for common integration problems and workarounds.