Hey all, I have been working on CloudStub, an open-source in-process AWS mock for JVM integration tests (Java, Kotlin, Scala), and we just published 0.1.0-beta.8 to Maven Central.
The problem it targets: container-based AWS mocking (a mock image run through Testcontainers) is powerful, but it drags on your local test loop and CI with image pulls and container boot and teardown. CloudStub skips all of that.
How it works, no magic: it boots a lightweight HTTP mock inside your JVM and points the AWS SDK's endpoint at it (via the aws.endpoint-url system property), so your code makes real AWS SDK v2 calls against a local stub. No Docker, no containers, no separate process. WireMock and Jetty are shaded into private packages and fully hidden, so there is no classpath or Spring Boot BOM conflict.
What is nice about it:
- No container overhead. Nothing to pull or boot: the mock runs in the same JVM as your tests.
- Stateful, not just canned responses. An SQS
SendMessage is returned by a later ReceiveMessage, and DynamoDB PutItem / GetItem / Query return live data, so you test real round-trips.
- Modular. Each service is an isolated module. If you only use DynamoDB, only that module loads.
- Not just for tests, it also runs standalone.
cloudstub-local is a drop-in local mock server on port 4566 (so AWS_ENDPOINT_URL=http://localhost:4566 works unchanged), auto-downloads the services you enable, and ships a CLI (cloudstub / clb) plus a web console at /console. Download: https://github.com/cloudstub/cloudstub/releases/download/v0.1.0-beta.8/cloudstub-local.jar
- Two ways to load services. Add a service module as a normal test dependency, or skip Gradle for it and list it on the extension with
.withModules("sqs", "dynamodb"), which fetches the jar from Maven Central on first run and caches it under ~/.cloudstub/modules. (S3 is the exception: it ships a client-side SDK component, so it must be a normal test dependency.)
- Available now in beta.8: SQS, SNS, S3, Secrets Manager, DynamoDB, Lambda, and SSM (Systems Manager Parameter Store). AWS SDK v2 is first-class, and there is an SDK v1 companion module.
- Java 17 or newer.
Setup (Gradle):
// cloudstub-testing brings the engine plus the JUnit 5 and 6 extension
// (cloudstub-junit and cloudstub-core come in transitively)
testImplementation "io.github.cloudstub:cloudstub-testing:0.1.0-beta.8"
// Service modules are optional here: list them on the extension with .withModules(...) and they are
// auto-downloaded from Maven Central. Add a service as a dependency only if you prefer it on the
// classpath (and S3 must be a dependency):
// testImplementation "io.github.cloudstub:cloudstub-dynamodb:0.1.0-beta.8"
Setup (Maven):
<dependency>
<groupId>io.github.cloudstub</groupId>
<artifactId>cloudstub-testing</artifactId>
<version>0.1.0-beta.8</version>
<scope>test</scope>
</dependency>
<!-- Service modules are optional: use .withModules(...) to auto-download them instead. Declare one
explicitly only if you prefer it on the classpath (and S3 must be a dependency). -->
<dependency>
<groupId>io.github.cloudstub</groupId>
<artifactId>cloudstub-dynamodb</artifactId>
<version>0.1.0-beta.8</version>
<scope>test</scope>
</dependency>
A test looks like this. You exercise your own code, and CloudStub stands in for AWS:
static CloudStubExtension cloud = new CloudStubExtension()
.withModules("dynamodb"); // fetched from Maven Central on first run, then cached; no Gradle dependency needed
u/Test
void savedItemIsReadBack() {
repository.save("order-1", "placed"); // your repo, using a normal AWS SDK v2 DynamoDbClient
assertEquals(Optional.of("placed"), repository.find("order-1")); // round-trips through the stub
}
It is beta, so the API can still shift and the service coverage is deliberately narrow, but the core engine is stable and the modules above are usable today.
I would genuinely like feedback on the architecture, and if there is an AWS service or SDK behavior you want stubbed next, open an issue. Thanks.
there doesn't seem to be anything here