You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/04/13 13:35:22 UTC

[camel-spring-boot] branch main updated: CAMEL-17920 add tests in camel-aws2-s3-starter (#518)

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git


The following commit(s) were added to refs/heads/main by this push:
     new 9349b819132 CAMEL-17920 add tests in camel-aws2-s3-starter (#518)
9349b819132 is described below

commit 9349b819132d1b629d82071a4be23ff02b76a538
Author: JiriOndrusek <on...@gmail.com>
AuthorDate: Wed Apr 13 15:35:18 2022 +0200

    CAMEL-17920 add tests in camel-aws2-s3-starter (#518)
---
 components-starter/camel-aws2-s3-starter/pom.xml   |  12 ++
 .../org/apache/camel/component/aws2/s3/BaseS3.java |  75 +++++++++
 .../component/aws2/s3/S3BatchConsumerTest.java     | 116 +++++++++++++
 .../camel/component/aws2/s3/S3ComponentTest.java   | 145 ++++++++++++++++
 .../aws2/s3/S3CopyObjectCustomerKeyTest.java       | 182 +++++++++++++++++++++
 .../aws2/s3/S3CopyObjectOperationTest.java         |  98 +++++++++++
 .../aws2/s3/S3CreateDownloadLinkOperationTest.java | 111 +++++++++++++
 .../aws2/s3/S3ListObjectsOperationTest.java        | 153 +++++++++++++++++
 .../aws2/s3/S3MoveAfterReadConsumerTest.java       | 126 ++++++++++++++
 .../aws2/s3/S3MultipartUploadOperationTest.java    | 110 +++++++++++++
 .../aws2/s3/S3ObjectRangeOperationTest.java        | 122 ++++++++++++++
 .../camel/component/aws2/s3/S3PojoAsBodyTest.java  |  92 +++++++++++
 .../s3/S3SimpleEncryptedUploadOperationTest.java   | 123 ++++++++++++++
 .../aws2/s3/S3StreamUploadOperationTest.java       | 101 ++++++++++++
 .../src/test/resources/empty.txt                   | Bin 0 -> 5242880 bytes
 15 files changed, 1566 insertions(+)

diff --git a/components-starter/camel-aws2-s3-starter/pom.xml b/components-starter/camel-aws2-s3-starter/pom.xml
index f9c773238fd..d5445b44749 100644
--- a/components-starter/camel-aws2-s3-starter/pom.xml
+++ b/components-starter/camel-aws2-s3-starter/pom.xml
@@ -47,6 +47,18 @@
       </exclusions>
       <!--END OF GENERATED CODE-->
     </dependency>
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-infra-aws-v2</artifactId>
+      <version>${camel-version}</version>
+      <type>test-jar</type>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.awaitility</groupId>
+      <artifactId>awaitility</artifactId>
+      <scope>test</scope>
+    </dependency>
     <!--START OF GENERATED CODE-->
     <dependency>
       <groupId>org.apache.camel.springboot</groupId>
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/BaseS3.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/BaseS3.java
new file mode 100644
index 00000000000..1727cc5c789
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/BaseS3.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.infra.aws.common.services.AWSService;
+import org.apache.camel.test.infra.aws2.clients.AWSSDKClientUtils;
+import org.apache.camel.test.infra.aws2.services.AWSServiceFactory;
+import org.apache.camel.test.infra.common.SharedNameGenerator;
+import org.apache.camel.test.infra.common.TestEntityNameGenerator;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.extension.RegisterExtension;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import java.util.concurrent.TimeUnit;
+
+public class BaseS3 {
+
+    @Autowired
+    protected CamelContext context;
+
+    @Autowired
+    protected ProducerTemplate template;
+
+    @RegisterExtension
+    public static AWSService service = AWSServiceFactory.createDynamodbService();
+
+    @RegisterExtension
+    public static SharedNameGenerator sharedNameGenerator = new TestEntityNameGenerator();
+
+    protected void assertMockEndpointsSatisfied() throws InterruptedException {
+        MockEndpoint.assertIsSatisfied(this.context);
+    }
+
+    protected void assertMockEndpointsSatisfied(long timeout) throws InterruptedException {
+        MockEndpoint.assertIsSatisfied(this.context, timeout, TimeUnit.MILLISECONDS);
+    }
+
+    @AfterAll
+    private static void closeClient() {
+        service.close();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public static class TestConfiguration {
+
+        @Bean
+        public S3Client s3Client(CamelContext context) {
+            return AWSSDKClientUtils.newS3Client();
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3BatchConsumerTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3BatchConsumerTest.java
new file mode 100644
index 00000000000..09be4998e6b
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3BatchConsumerTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePropertyKey;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+//Based on S3ConsumerIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3BatchConsumerTest.class,
+                S3BatchConsumerTest.TestConfiguration.class
+        }
+)
+public class S3BatchConsumerTest extends BaseS3 {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(3);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setBody("Test");
+            }
+        });
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test1.txt");
+                exchange.getIn().setBody("Test1");
+            }
+        });
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test2.txt");
+                exchange.getIn().setBody("Test2");
+            }
+        });
+
+        assertMockEndpointsSatisfied(10000);
+
+        final Exchange exchange1 = result.getExchanges().get(0);
+        Assertions.assertEquals(0, exchange1.getProperty(ExchangePropertyKey.BATCH_INDEX));
+        Assertions.assertEquals(2, exchange1.getProperty(ExchangePropertyKey.BATCH_SIZE));
+        Assertions.assertFalse((Boolean)exchange1.getProperty(ExchangePropertyKey.BATCH_COMPLETE));
+        final Exchange exchange2 = result.getExchanges().get(1);
+        Assertions.assertEquals(1, exchange2.getProperty(ExchangePropertyKey.BATCH_INDEX));
+        Assertions.assertEquals(2, exchange2.getProperty(ExchangePropertyKey.BATCH_SIZE));
+        Assertions.assertTrue((Boolean)exchange2.getProperty(ExchangePropertyKey.BATCH_COMPLETE));
+        final Exchange exchange3 = result.getExchanges().get(2);
+        Assertions.assertEquals(0, exchange3.getProperty(ExchangePropertyKey.BATCH_INDEX));
+        Assertions.assertEquals(1 , exchange3.getProperty(ExchangePropertyKey.BATCH_SIZE));
+        Assertions.assertTrue((Boolean)exchange3.getProperty(ExchangePropertyKey.BATCH_COMPLETE));
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder() {
+            final  String awsEndpoint = "aws2-s3://mycamel?autoCreateBucket=true&maxMessagesPerPoll=2";
+
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:putObject").startupOrder(1).to(awsEndpoint);
+
+                    from(awsEndpoint).startupOrder(2).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ComponentTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ComponentTest.java
new file mode 100644
index 00000000000..a20bf7c516f
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ComponentTest.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Message;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+// Based on S3ComponentManualIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3ComponentTest.class,
+                S3ComponentTest.TestConfiguration.class
+        }
+)
+public class S3ComponentTest extends BaseS3 {
+
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendInOnly() throws Exception {
+        result.reset();
+        result.expectedMessageCount(2);
+
+        Exchange exchange1 = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest1");
+                exchange.getIn().setBody("This is my bucket content.");
+            }
+        });
+
+        Exchange exchange2 = template.send("direct:start", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest2");
+                exchange.getIn().setBody("This is my bucket content.");
+            }
+        });
+
+        assertMockEndpointsSatisfied(10_000);
+
+        assertResultExchange(result.getExchanges().get(0));
+        assertResultExchange(result.getExchanges().get(1));
+
+        assertResponseMessage(exchange1.getIn());
+        assertResponseMessage(exchange2.getIn());
+    }
+
+    @Test
+    public void sendInOut() throws Exception {
+        result.reset();
+        result.expectedMessageCount(1);
+
+        Exchange exchange = template.send("direct:start", ExchangePattern.InOut, new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest");
+                exchange.getIn().setBody("This is my bucket content.");
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+
+        assertResultExchange(result.getExchanges().get(0));
+
+        assertResponseMessage(exchange.getMessage());
+    }
+
+    private void assertResultExchange(Exchange resultExchange) {
+        assertEquals("This is my bucket content.", resultExchange.getIn().getBody(String.class));
+        assertEquals("mycamelbucket", resultExchange.getIn().getHeader(AWS2S3Constants.BUCKET_NAME));
+        assertTrue(resultExchange.getIn().getHeader(AWS2S3Constants.KEY, String.class).startsWith("CamelUnitTest"));
+        assertEquals("null", resultExchange.getIn().getHeader(AWS2S3Constants.VERSION_ID));
+        // enabled
+        // on
+        // this
+        // bucket
+        assertNotNull(resultExchange.getIn().getHeader(AWS2S3Constants.LAST_MODIFIED));
+        assertEquals("application/octet-stream", resultExchange.getIn().getHeader(AWS2S3Constants.CONTENT_TYPE));
+        assertNull(resultExchange.getIn().getHeader(AWS2S3Constants.CONTENT_ENCODING));
+        assertEquals(26L, resultExchange.getIn().getHeader(AWS2S3Constants.CONTENT_LENGTH));
+        assertNull(resultExchange.getIn().getHeader(AWS2S3Constants.CONTENT_DISPOSITION));
+        assertNull(resultExchange.getIn().getHeader(AWS2S3Constants.CONTENT_MD5));
+        assertNull(resultExchange.getIn().getHeader(AWS2S3Constants.CACHE_CONTROL));
+    }
+
+    private void assertResponseMessage(Message message) {
+        assertNull(message.getHeader(AWS2S3Constants.VERSION_ID));
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder() {
+            final String s3EndpointUri
+                    = "aws2-s3://mycamelbucket?autoCreateBucket=true";
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start").log("start start start start {body}").to(s3EndpointUri);
+
+                    from(s3EndpointUri).log("finish finish finish fiisht {body}").to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CopyObjectCustomerKeyTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CopyObjectCustomerKeyTest.java
new file mode 100644
index 00000000000..6de9b2929f0
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CopyObjectCustomerKeyTest.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.GetObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetObjectResponse;
+import software.amazon.awssdk.utils.Md5Utils;
+
+import javax.crypto.KeyGenerator;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.util.Base64;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
+import static software.amazon.awssdk.services.s3.model.ServerSideEncryption.AES256;
+
+//Based on S3CopyObjectCustomerKeyIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3CopyObjectCustomerKeyTest.class,
+                S3CopyObjectCustomerKeyTest.TestConfiguration.class
+        }
+)
+public class S3CopyObjectCustomerKeyTest extends BaseS3 {
+
+    byte[] secretKey = generateSecretKey();
+    String b64Key = Base64.getEncoder().encodeToString(secretKey);
+    String b64KeyMd5 = Md5Utils.md5AsBase64(secretKey);
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setBody("Test");
+            }
+        });
+
+        template.send("direct:copyObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setHeader(AWS2S3Constants.DESTINATION_KEY, "test1.txt");
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_DESTINATION_NAME, "mycamel1");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.copyObject);
+            }
+        });
+
+        Exchange res = template.request("direct:getObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                GetObjectRequest getObjectRequest = GetObjectRequest.builder()
+                        .key("test1.txt")
+                        .bucket("mycamel1")
+                        .sseCustomerKey(b64Key)
+                        .sseCustomerAlgorithm(AES256.name())
+                        .sseCustomerKeyMD5(b64KeyMd5)
+                        .build();
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.getObject);
+                exchange.getIn().setBody(getObjectRequest);
+            }
+        });
+
+        ResponseInputStream<GetObjectResponse> s3 = res.getIn().getBody(ResponseInputStream.class);
+
+        assertEquals("Test", readInputStream(s3));
+
+        Exchange res1 = template.request("direct:listObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+            }
+        });
+
+        List response = res1.getIn().getBody(List.class);
+
+        assertEquals(1, response.size());
+
+        assertMockEndpointsSatisfied();
+    }
+
+    protected static byte[] generateSecretKey() {
+        KeyGenerator generator;
+        try {
+            generator = KeyGenerator.getInstance("AES");
+            generator.init(256, new SecureRandom());
+            return generator.generateKey().getEncoded();
+        } catch (Exception e) {
+            fail("Unable to generate symmetric key: " + e.getMessage());
+            return null;
+        }
+    }
+
+    private String readInputStream(ResponseInputStream<GetObjectResponse> s3Object) throws IOException {
+        StringBuilder textBuilder = new StringBuilder();
+        try (Reader reader
+                     = new BufferedReader(new InputStreamReader(s3Object, Charset.forName(StandardCharsets.UTF_8.name())))) {
+            int c = 0;
+            while ((c = reader.read()) != -1) {
+                textBuilder.append((char) c);
+            }
+        }
+        return textBuilder.toString();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsEndpoint = "aws2-s3://mycamel?autoCreateBucket=true&useCustomerKey=true&customerKeyId=RAW(" + b64Key
+                            + ")&customerKeyMD5=RAW(" + b64KeyMd5 + ")&customerAlgorithm=" + AES256.name();
+                    String awsEndpoint1 = "aws2-s3://mycamel1?autoCreateBucket=true&pojoRequest=true";
+                    String awsEndpoint2 = "aws2-s3://mycamel1?autoCreateBucket=true";
+
+                    from("direct:putObject").setHeader(AWS2S3Constants.KEY, constant("test.txt")).setBody(constant("Test"))
+                            .to(awsEndpoint);
+
+                    from("direct:copyObject").to(awsEndpoint);
+
+                    from("direct:listObject").to(awsEndpoint2);
+
+                    from("direct:getObject").to(awsEndpoint1).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CopyObjectOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CopyObjectOperationTest.java
new file mode 100644
index 00000000000..e8731904dde
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CopyObjectOperationTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.services.s3.S3Client;
+
+//Based on S3CopyObjectOperationManualIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3CopyObjectOperationTest.class,
+                S3CopyObjectOperationTest.TestConfiguration.class
+        }
+)
+public class S3CopyObjectOperationTest extends BaseS3 {
+    private static final String ACCESS_KEY = System.getProperty("aws.manual.access.key");
+    private static final String SECRET_KEY = System.getProperty("aws.manual.secret.key");
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:originalBucket", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setBody("Test");
+            }
+        });
+
+        template.send("direct:originalBucket", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setHeader(AWS2S3Constants.DESTINATION_KEY, "test1.txt");
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_DESTINATION_NAME, "mycamel1");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.copyObject);
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsOriginalEndpoint = "aws2-s3://mycamel?autoCreateBucket=true";
+                    String awsCopyedEndpoint = "aws2-s3://mycamel1?autoCreateBucket=true";
+
+                    from("direct:originalBucket").to(awsOriginalEndpoint);
+
+                    from(awsCopyedEndpoint).to(result);
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CreateDownloadLinkOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CreateDownloadLinkOperationTest.java
new file mode 100644
index 00000000000..84c8be7652b
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3CreateDownloadLinkOperationTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.services.s3.S3Client;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+//Based on S3CreateDownloadLinkOperationIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3CreateDownloadLinkOperationTest.class,
+                S3CreateDownloadLinkOperationTest.TestConfiguration.class
+        }
+)
+public class S3CreateDownloadLinkOperationTest extends BaseS3 {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:addObject", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest2");
+                exchange.getIn().setBody("This is my bucket content.");
+                exchange.getIn().removeHeader(AWS2S3Constants.S3_OPERATION);
+            }
+        });
+
+        Exchange ex1 = template.request("direct:createDownloadLink", new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest2");
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel2");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.createDownloadLink);
+            }
+        });
+
+        Exchange ex2 = template.request("direct:createDownloadLinkWithoutCredentials", new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest2");
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel2");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.createDownloadLink);
+            }
+        });
+
+        assertNotNull(ex1.getMessage().getBody());
+        assertNull(ex2.getMessage().getBody());
+        assertMockEndpointsSatisfied();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsEndpoint = "aws2-s3://mycamel2?autoCreateBucket=true";
+
+                    from("direct:addObject").to(awsEndpoint);
+
+                    from("direct:createDownloadLinkWithoutCredentials").to(awsEndpoint).to("mock:result");
+
+                    from("direct:createDownloadLink").to(awsEndpoint + "&accessKey=xxx&secretKey=yyy&region=eu-west-1")
+                            .to("mock:result");
+                }
+            };
+        }
+    }
+
+
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ListObjectsOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ListObjectsOperationTest.java
new file mode 100644
index 00000000000..54dec838068
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ListObjectsOperationTest.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.Bucket;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+//Based on S3ListObjectsOperationIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3ListObjectsOperationTest.class,
+                S3ListObjectsOperationTest.TestConfiguration.class
+        }
+)
+public class S3ListObjectsOperationTest extends BaseS3 {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+
+        Exchange ex = template.send("direct:listBucket", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listBuckets);
+            }
+        });
+
+        List<Bucket> buckets = ex.getMessage().getBody(List.class);
+        assertEquals(1, buckets.size());
+        assertEquals("mycamel2", buckets.get(0).name());
+
+        template.send("direct:addObject", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest2");
+                exchange.getIn().setBody("This is my bucket content.");
+                exchange.getIn().removeHeader(AWS2S3Constants.S3_OPERATION);
+            }
+        });
+
+        ex = template.request("direct:listObjects", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel2");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+            }
+        });
+
+        List<S3Object> resp = ex.getMessage().getBody(List.class);
+        assertEquals(1, resp.size());
+        assertEquals("CamelUnitTest2", resp.get(0).key());
+
+        template.send("direct:deleteObject", ExchangePattern.InOnly, new Processor() {
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "CamelUnitTest2");
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel2");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.deleteObject);
+            }
+        });
+
+        //verify that is deleted
+        ex = template.request("direct:listObjects", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel2");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+            }
+        });
+
+        resp = ex.getMessage().getBody(List.class);
+        assertTrue(resp.isEmpty());
+
+        template.send("direct:deleteBucket", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel2");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.deleteBucket);
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsEndpoint = "aws2-s3://mycamel2?autoCreateBucket=true";
+
+                    from("direct:listBucket").to(awsEndpoint);
+
+                    from("direct:addObject").to(awsEndpoint);
+
+                    from("direct:deleteObject").to(awsEndpoint);
+
+                    from("direct:listObjects").to(awsEndpoint);
+
+                    from("direct:deleteBucket").to(awsEndpoint).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3MoveAfterReadConsumerTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3MoveAfterReadConsumerTest.java
new file mode 100644
index 00000000000..4ecde5c39d6
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3MoveAfterReadConsumerTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import org.testcontainers.shaded.org.awaitility.Awaitility;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+//Based on S3ConsumerIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3MoveAfterReadConsumerTest.class,
+                S3MoveAfterReadConsumerTest.TestConfiguration.class
+        }
+)
+public class S3MoveAfterReadConsumerTest extends BaseS3 {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(3);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setBody("Test");
+            }
+        });
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test1.txt");
+                exchange.getIn().setBody("Test1");
+            }
+        });
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test2.txt");
+                exchange.getIn().setBody("Test2");
+            }
+        });
+
+        assertMockEndpointsSatisfied(10_000);
+
+        //wait for finish
+        Awaitility.await().atMost(10, TimeUnit.SECONDS).until(
+            () -> {
+                List<S3Object> results = template.request("direct:listObjects", new Processor() {
+                    @Override
+                    public void process(Exchange exchange) {
+                        exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "already-read");
+                        exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+                    }
+                }).getMessage().getBody(List.class);
+
+                return results.size() == 3 && "movedPrefixtest.txtmovedSuffix".equals(results.get(0).key());
+            });
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder() {
+            final  String awsEndpoint = "aws2-s3://mycamel?autoCreateBucket=true";
+
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:putObject").startupOrder(1).to(awsEndpoint).to("mock:result");
+
+                    from("aws2-s3://mycamel?moveAfterRead=true&destinationBucket=already-read&autoCreateBucket=true&destinationBucketPrefix=RAW(movedPrefix)&destinationBucketSuffix=RAW(movedSuffix)")
+                            .to("log:foo");
+
+                    from("direct:listObjects").to("aws2-s3://mycamel?autoCreateBucket=false");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3MultipartUploadOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3MultipartUploadOperationTest.java
new file mode 100644
index 00000000000..1863c1c4f7b
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3MultipartUploadOperationTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.infra.aws2.clients.AWSSDKClientUtils;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.GetObjectRequest;
+import software.amazon.awssdk.services.s3.model.GetObjectResponse;
+
+import java.io.File;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+//Based on S3MultipartUploadOperationIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3MultipartUploadOperationTest.class,
+                S3MultipartUploadOperationTest.TestConfiguration.class
+        }
+)
+public class S3MultipartUploadOperationTest extends BaseS3 {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "empty.txt");
+                exchange.getIn().setBody(new File("src/test/resources/empty.txt"));
+            }
+        });
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Test
+    public void sendInWithContentType() {
+        result.expectedMessageCount(1);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "camel-content-type.txt");
+                exchange.getIn().setBody(new File("src/test/resources/empty.txt"));
+                exchange.getIn().setHeader(AWS2S3Constants.CONTENT_TYPE, "application/text");
+            }
+        });
+
+        S3Client s = AWSSDKClientUtils.newS3Client();
+        ResponseInputStream<GetObjectResponse> response
+                = s.getObject(GetObjectRequest.builder().bucket("mycamel").key("camel-content-type.txt").build());
+        assertEquals("application/text", response.response().contentType());
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsEndpoint = "aws2-s3://mycamel?multiPartUpload=true&autoCreateBucket=true";
+
+                    from("direct:putObject").to(awsEndpoint).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ObjectRangeOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ObjectRangeOperationTest.java
new file mode 100644
index 00000000000..d6c2c5e0a44
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3ObjectRangeOperationTest.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.GetObjectResponse;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
+//Based on S3ObjectRangeOperationManualIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3ObjectRangeOperationTest.class,
+                S3ObjectRangeOperationTest.TestConfiguration.class
+        }
+)
+public class S3ObjectRangeOperationTest extends BaseS3 {
+    private static final Logger LOG = LoggerFactory.getLogger(S3ObjectRangeOperationTest.class);
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "element.txt");
+                exchange.getIn().setBody("0123456789");
+            }
+        });
+
+
+        template.send("direct:getObjectRange", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "element.txt");
+                exchange.getIn().setHeader(AWS2S3Constants.RANGE_START, 0);
+                exchange.getIn().setHeader(AWS2S3Constants.RANGE_END, 2);
+            }
+        });
+        assertMockEndpointsSatisfied();
+        Exchange exchange = result.getExchanges().get(0);
+        ResponseInputStream<GetObjectResponse> s3 = exchange.getIn().getBody(ResponseInputStream.class);
+        Assertions.assertEquals("012", readInputStream(s3));
+    }
+
+    private String readInputStream(ResponseInputStream<GetObjectResponse> s3Object) throws IOException {
+        StringBuilder textBuilder = new StringBuilder();
+        try (Reader reader = new BufferedReader(new InputStreamReader(s3Object, Charset.forName(StandardCharsets.UTF_8.name())))) {
+            int c = 0;
+            while ((c = reader.read()) != -1) {
+                textBuilder.append((char) c);
+            }
+        }
+        return textBuilder.toString();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsEndpoint = "aws2-s3://mycamelbucket?operation=getObjectRange&autoCreateBucket=false";
+                    String awsOriginalEndpoint = "aws2-s3://mycamelbucket?autoCreateBucket=true";
+
+                    from("direct:putObject").startupOrder(1).to(awsOriginalEndpoint);
+
+                    from("direct:getObjectRange").startupOrder(2).to(awsEndpoint).to("mock:result");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3PojoAsBodyTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3PojoAsBodyTest.java
new file mode 100644
index 00000000000..dc2e53aa6aa
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3PojoAsBodyTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.ListObjectsRequest;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+//Based on S3CopyObjectOperationManualIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3PojoAsBodyTest.class,
+                S3PojoAsBodyTest.TestConfiguration.class
+        }
+)
+public class S3PojoAsBodyTest extends BaseS3 {
+
+    @Test
+    public void sendIn() throws Exception {
+
+        template.send("direct:send", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "test.txt");
+                exchange.getIn().setBody("Test");
+            }
+        });
+
+        Exchange ex = template.send("direct:list", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setBody(ListObjectsRequest.builder().bucket("mycamel").build());
+            }
+        });
+
+        List<S3Object> resp = ex.getMessage().getBody(List.class);
+        assertEquals(1, resp.size());
+        assertEquals("test.txt", resp.get(0).key());
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:send").to("aws2-s3://mycamel?autoCreateBucket=true");
+
+                    from("direct:list").to("aws2-s3://mycamel?autoCreateBucket=true&operation=listObjects&pojoRequest=true");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3SimpleEncryptedUploadOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3SimpleEncryptedUploadOperationTest.java
new file mode 100644
index 00000000000..bcb7f6b6982
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3SimpleEncryptedUploadOperationTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.infra.aws2.clients.AWSSDKClientUtils;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.services.kms.model.CreateKeyRequest;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+//Based on S3SimpleEncryptedUploadOperationIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3SimpleEncryptedUploadOperationTest.class,
+                S3SimpleEncryptedUploadOperationTest.TestConfiguration.class
+        }
+)
+public class S3SimpleEncryptedUploadOperationTest extends BaseS3 {
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @EndpointInject("mock:resultGet")
+    private MockEndpoint resultGet;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1);
+        resultGet.expectedMessageCount(1);
+
+        template.send("direct:putObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "camel.txt");
+                exchange.getIn().setBody("Camel rocks!");
+            }
+        });
+
+        template.request("direct:listObjects", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.BUCKET_NAME, "mycamel");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+            }
+        });
+
+        Exchange c = template.request("direct:getObject", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.KEY, "camel.txt");
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.getObject);
+            }
+        });
+
+        List<S3Object> resp = result.getExchanges().get(0).getMessage().getBody(List.class);
+        assertEquals(1, resp.size());
+        assertEquals("camel.txt", resp.get(0).key());
+
+        assertEquals("Camel rocks!", c.getIn().getBody(String.class));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String key = AWSSDKClientUtils.newKMSClient().createKey(CreateKeyRequest.builder().description("Test_key").build())
+                            .keyMetadata().keyId();
+                    String awsEndpoint = "aws2-s3://mycamel?autoCreateBucket=true&useAwsKMS=true&awsKMSKeyId=" + key;
+
+                    from("direct:putObject").to(awsEndpoint);
+
+                    from("direct:listObjects").to(awsEndpoint).to("mock:result");
+
+                    from("direct:getObject").to("aws2-s3://mycamel?autoCreateBucket=true").to("mock:resultGet");
+                }
+            };
+        }
+    }
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3StreamUploadOperationTest.java b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3StreamUploadOperationTest.java
new file mode 100644
index 00000000000..18878b18266
--- /dev/null
+++ b/components-starter/camel-aws2-s3-starter/src/test/java/org/apache/camel/component/aws2/s3/S3StreamUploadOperationTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.s3;
+
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.annotation.DirtiesContext;
+import software.amazon.awssdk.services.s3.S3Client;
+import software.amazon.awssdk.services.s3.model.S3Object;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+//based on S3StreamUploadOperationIT
+@DirtiesContext
+@CamelSpringBootTest
+@SpringBootTest(
+        classes = {
+                CamelAutoConfiguration.class,
+                S3StreamUploadOperationTest.class,
+                S3StreamUploadOperationTest.TestConfiguration.class
+        }
+)
+public class S3StreamUploadOperationTest extends BaseS3 {
+
+
+    @EndpointInject("mock:result")
+    private MockEndpoint result;
+
+    @Test
+    public void sendIn() throws Exception {
+        result.expectedMessageCount(1000);
+
+        for (int i = 0; i < 1000; i++) {
+            template.sendBody("direct:stream1", "Andrea\n");
+        }
+
+        assertMockEndpointsSatisfied();
+
+        Exchange ex = template.request("direct:listObjects", new Processor() {
+
+            @Override
+            public void process(Exchange exchange) {
+                exchange.getIn().setHeader(AWS2S3Constants.S3_OPERATION, AWS2S3Operations.listObjects);
+            }
+        });
+
+        List<S3Object> resp = ex.getMessage().getBody(List.class);
+        assertEquals(40, resp.size());
+    }
+
+
+    // *************************************
+    // Config
+    // *************************************
+
+    @Configuration
+    public class TestConfiguration extends  BaseS3.TestConfiguration {
+        @Bean
+        public RouteBuilder routeBuilder(S3Client s3Client) {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    String awsEndpoint1
+                            = "aws2-s3://mycamel-1?autoCreateBucket=true&streamingUploadMode=true&keyName=fileTest.txt&batchMessageNumber=25&namingStrategy=random";
+
+                    from("direct:stream1").to(awsEndpoint1).to("mock:result");
+
+                    String awsEndpoint = "aws2-s3://mycamel-1?autoCreateBucket=true";
+
+                    from("direct:listObjects").to(awsEndpoint);
+                }
+            };
+        }
+    }
+
+}
diff --git a/components-starter/camel-aws2-s3-starter/src/test/resources/empty.txt b/components-starter/camel-aws2-s3-starter/src/test/resources/empty.txt
new file mode 100644
index 00000000000..3995316735a
Binary files /dev/null and b/components-starter/camel-aws2-s3-starter/src/test/resources/empty.txt differ