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 81213fc  [CAMEL-17677]add tests in camel-jira-starter (#439)
81213fc is described below

commit 81213fc5e6c8d8a25ff10d0b5039386514e0626b
Author: Freeman(Yue) Fang <freeman.f...@gmail.com>
AuthorDate: Wed Feb 23 01:09:40 2022 -0500

    [CAMEL-17677]add tests in camel-jira-starter (#439)
---
 components-starter/camel-jira-starter/pom.xml      |  23 ++
 .../springboot/test/AddCommentProducerTest.java    | 175 +++++++++++++
 .../springboot/test/AddIssueLinkProducerTest.java  | 272 +++++++++++++++++++++
 .../jira/springboot/test/AddIssueProducerTest.java | 239 ++++++++++++++++++
 .../springboot/test/AddWorkLogProducerTest.java    | 251 +++++++++++++++++++
 .../springboot/test/AttachFileProducerTest.java    | 196 +++++++++++++++
 .../springboot/test/DeleteIssueProducerTest.java   | 163 ++++++++++++
 .../springboot/test/FetchCommentsProducerTest.java | 177 ++++++++++++++
 .../springboot/test/FetchIssueProducerTest.java    | 174 +++++++++++++
 .../jira/springboot/test/JiraTestConstants.java    |  28 +++
 .../springboot/test/NewCommentsConsumerTest.java   | 236 ++++++++++++++++++
 .../springboot/test/NewIssuesConsumerTest.java     | 205 ++++++++++++++++
 .../test/TransitionIssueProducerTest.java          | 173 +++++++++++++
 .../springboot/test/UpdateIssueProducerTest.java   | 216 ++++++++++++++++
 .../component/jira/springboot/test/Utils.java      | 194 +++++++++++++++
 .../springboot/test/WatchUpdatesConsumerTest.java  | 220 +++++++++++++++++
 .../jira/springboot/test/WatcherProducerTest.java  | 264 ++++++++++++++++++++
 17 files changed, 3206 insertions(+)

diff --git a/components-starter/camel-jira-starter/pom.xml 
b/components-starter/camel-jira-starter/pom.xml
index 775b48d..7714147 100644
--- a/components-starter/camel-jira-starter/pom.xml
+++ b/components-starter/camel-jira-starter/pom.xml
@@ -47,6 +47,29 @@
       </exclusions>
       <!--END OF GENERATED CODE-->
     </dependency>
+    <!-- Testing dependencies -->
+    <dependency>
+      <groupId>org.apache.camel</groupId>
+      <artifactId>camel-test-spring-junit5</artifactId>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.camel</groupId>
+          <artifactId>camel-spring-xml</artifactId>
+        </exclusion>
+      </exclusions>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.awaitility</groupId>
+      <artifactId>awaitility</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <version>${spring-boot-version}</version>
+      <scope>test</scope>
+    </dependency>
     <!--START OF GENERATED CODE-->
     <dependency>
       <groupId>org.apache.camel.springboot</groupId>
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddCommentProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddCommentProducerTest.java
new file mode 100644
index 0000000..80b8dd8
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddCommentProducerTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssueWithComments;
+import static org.apache.camel.component.jira.springboot.test.Utils.newComment;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Comment;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.mockito.stubbing.Answer;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        AddCommentProducerTest.class,
+        AddCommentProducerTest.TestConfiguration.class
+    }
+)
+
+public class AddCommentProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    static Issue issue;
+    
+    static String comment;
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                when(issueRestClient.addComment(any(), 
any())).then((Answer<Void>) inv -> {
+                    Collection<Comment> comments = new ArrayList<>();
+                    for (Comment c : backendIssue.getComments()) {
+                        comments.add(c);
+                    }
+                    comments.add(newComment(backendIssue.getId(), 
comments.size() + 1, comment));
+                    backendIssue = 
createIssueWithComments(backendIssue.getId(), comments);
+                    return null;
+                });
+                backendIssue = createIssueWithComments(1, 1);
+                when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(backendIssue));
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void verifyLastComment() throws InterruptedException {
+        template.sendBodyAndHeader(comment, ISSUE_KEY, backendIssue.getKey());
+
+        Issue issue = issueRestClient.getIssue(backendIssue.getKey()).claim();
+        String lastComment = null;
+        for (Comment c : issue.getComments()) {
+            lastComment = c.getBody();
+        }
+        assertEquals(comment, lastComment);
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    comment = "A new test comment " + new Date();
+                    from("direct:start")
+                            .to("jira://addComment?jiraUrl=" + 
JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddIssueLinkProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddIssueLinkProducerTest.java
new file mode 100644
index 0000000..177fb6d
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddIssueLinkProducerTest.java
@@ -0,0 +1,272 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.CHILD_ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static org.apache.camel.component.jira.JiraConstants.LINK_TYPE;
+import static org.apache.camel.component.jira.JiraConstants.PARENT_ISSUE_KEY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssueWithLinks;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.newIssueLink;
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.apache.camel.test.junit5.TestSupport.assertStringContains;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.IssueLink;
+import com.atlassian.jira.rest.client.api.domain.input.LinkIssuesInput;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+import org.mockito.stubbing.Answer;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        AddIssueLinkProducerTest.class,
+        AddIssueLinkProducerTest.TestConfiguration.class
+    }
+)
+
+public class AddIssueLinkProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue parentIssue;
+    static Issue childIssue;
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                parentIssue = createIssue(1);
+                childIssue = createIssue(2);
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void testAddIssueLink() throws InterruptedException {
+        String comment = "A new test comment " + new Date();
+        String linkType = "Relates";
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(PARENT_ISSUE_KEY, parentIssue.getKey());
+        headers.put(CHILD_ISSUE_KEY, childIssue.getKey());
+        headers.put(LINK_TYPE, linkType);
+
+        when(issueRestClient.linkIssue(any(LinkIssuesInput.class)))
+                .then((Answer<Void>) inv -> {
+                    Collection<IssueLink> links = new ArrayList<>();
+                    links.add(newIssueLink(childIssue.getId(), 1, comment));
+                    parentIssue = createIssueWithLinks(parentIssue.getId(), 
links);
+                    return null;
+                });
+
+        template.sendBodyAndHeaders(comment, headers);
+
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient).linkIssue(any(LinkIssuesInput.class));
+    }
+
+    @Test
+    public void testAddIssueLinkNoComment() throws InterruptedException {
+        String linkType = "Relates";
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(PARENT_ISSUE_KEY, parentIssue.getKey());
+        headers.put(CHILD_ISSUE_KEY, childIssue.getKey());
+        headers.put(LINK_TYPE, linkType);
+
+        when(issueRestClient.linkIssue(any(LinkIssuesInput.class)))
+                .then((Answer<Void>) inv -> {
+                    Collection<IssueLink> links = new ArrayList<>();
+                    links.add(newIssueLink(childIssue.getId(), 1, null));
+                    parentIssue = createIssueWithLinks(parentIssue.getId(), 
links);
+                    return null;
+                });
+
+        template.sendBodyAndHeaders(null, headers);
+
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient).linkIssue(any(LinkIssuesInput.class));
+    }
+
+    @Test
+    public void testAddIssueLinkMissingParentIssueKey() throws 
InterruptedException {
+        String comment = "A new test comment " + new Date();
+        String linkType = "Relates";
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(CHILD_ISSUE_KEY, childIssue.getKey());
+        headers.put(LINK_TYPE, linkType);
+
+        try {
+            template.sendBodyAndHeaders(comment, headers);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), PARENT_ISSUE_KEY);
+        }
+
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).linkIssue(any(LinkIssuesInput.class));
+    }
+
+    @Test
+    public void testAddIssueLinkMissingChildIssueKey() throws 
InterruptedException {
+        String comment = "A new test comment " + new Date();
+        String linkType = "Relates";
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(PARENT_ISSUE_KEY, parentIssue.getKey());
+        headers.put(LINK_TYPE, linkType);
+
+        try {
+            template.sendBodyAndHeaders(comment, headers);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), CHILD_ISSUE_KEY);
+        }
+
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).linkIssue(any(LinkIssuesInput.class));
+    }
+
+    @Test
+    public void testAddIssueLinkMissingLinkType() throws InterruptedException {
+        String comment = "A new test comment " + new Date();
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(PARENT_ISSUE_KEY, parentIssue.getKey());
+        headers.put(CHILD_ISSUE_KEY, childIssue.getKey());
+
+        try {
+            template.sendBodyAndHeaders(comment, headers);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), LINK_TYPE);
+        }
+
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).linkIssue(any(LinkIssuesInput.class));
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start")
+                            .to("jira://addIssueLink?jiraUrl=" + 
JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddIssueProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddIssueProducerTest.java
new file mode 100644
index 0000000..b7449d3
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddIssueProducerTest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_ASSIGNEE;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_PRIORITY_ID;
+import static 
org.apache.camel.component.jira.JiraConstants.ISSUE_PRIORITY_NAME;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_PROJECT_KEY;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_SUMMARY;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_TYPE_ID;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_TYPE_NAME;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.KEY;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.userAssignee;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.MetadataRestClient;
+import com.atlassian.jira.rest.client.api.domain.BasicIssue;
+import com.atlassian.jira.rest.client.api.domain.BasicPriority;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.IssueType;
+import com.atlassian.jira.rest.client.api.domain.Priority;
+import 
com.atlassian.jira.rest.client.api.domain.input.ComplexIssueInputFieldValue;
+import com.atlassian.jira.rest.client.api.domain.input.IssueInput;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import io.atlassian.util.concurrent.Promise;
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        AddIssueProducerTest.class,
+        AddIssueProducerTest.TestConfiguration.class
+    }
+)
+
+public class AddIssueProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    static MetadataRestClient metadataRestClient;
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                metadataRestClient = mock(MetadataRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                
lenient().when(jiraClient.getMetadataClient()).thenReturn(metadataRestClient);
+
+                Map<Integer, IssueType> issueTypes = new HashMap<>();
+                issueTypes.put(1, new IssueType(null, 1L, "Bug", false, null, 
null));
+                issueTypes.put(2, new IssueType(null, 2L, "Task", false, null, 
null));
+                Promise<Iterable<IssueType>> promiseIssueTypes = 
Promises.promise(issueTypes.values());
+                
lenient().when(metadataRestClient.getIssueTypes()).thenReturn(promiseIssueTypes);
+
+                Map<Integer, Priority> issuePriorities = new HashMap<>();
+                issuePriorities.put(1, new Priority(null, 1L, "High", null, 
null, null));
+                issuePriorities.put(2, new Priority(null, 2L, "Low", null, 
null, null));
+                Promise<Iterable<Priority>> promisePriorities = 
Promises.promise(issuePriorities.values());
+                
lenient().when(metadataRestClient.getPriorities()).thenReturn(promisePriorities);
+
+                
lenient().when(issueRestClient.createIssue(any(IssueInput.class))).then(inv -> {
+                    IssueInput issueInput = inv.getArgument(0);
+                    String summary = (String) 
issueInput.getField("summary").getValue();
+                    Integer issueTypeId = 
Integer.parseInt(getValue(issueInput, "issuetype", "id"));
+                    IssueType issueType = issueTypes.get(issueTypeId);
+                    String project = getValue(issueInput, "project", "key");
+                    String description = (String) 
issueInput.getField("description").getValue();
+                    Integer priorityId = Integer.parseInt(getValue(issueInput, 
"priority", "id"));
+                    BasicPriority priority = issuePriorities.get(priorityId);
+                    backendIssue = createIssue(11L, summary, project, 
issueType, description, priority, userAssignee, null, null);
+                    BasicIssue basicIssue = new 
BasicIssue(backendIssue.getSelf(), backendIssue.getKey(), backendIssue.getId());
+                    return Promises.promise(basicIssue);
+                });
+                lenient().when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(backendIssue));
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    private String getValue(IssueInput issueInput, String field, String key) {
+        ComplexIssueInputFieldValue complexField = 
(ComplexIssueInputFieldValue) issueInput.getField(field).getValue();
+        return (String) complexField.getValuesMap().get(key);
+    }
+    
+    @Test
+    public void verifyIssueAdded() throws InterruptedException {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_PROJECT_KEY, KEY);
+        headers.put(ISSUE_TYPE_NAME, "Task");
+        headers.put(ISSUE_SUMMARY, "Demo Bug jira " + (new Date()));
+        headers.put(ISSUE_PRIORITY_NAME, "Low");
+        headers.put(ISSUE_ASSIGNEE, "tom");
+
+        template.sendBodyAndHeaders("Minha descrição jira " + (new Date()), 
headers);
+
+        Issue issue = issueRestClient.getIssue(backendIssue.getKey()).claim();
+        assertEquals(backendIssue, issue);
+        assertEquals(backendIssue.getIssueType(), issue.getIssueType());
+        assertEquals(backendIssue.getPriority(), issue.getPriority());
+        assertEquals(backendIssue.getSummary(), issue.getSummary());
+        assertEquals(backendIssue.getProject(), issue.getProject());
+        assertEquals(backendIssue.getDescription(), issue.getDescription());
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void verifyIssueAddedWithIds() throws InterruptedException {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_PROJECT_KEY, KEY);
+        headers.put(ISSUE_TYPE_ID, 2);
+        headers.put(ISSUE_SUMMARY, "Demo Bug jira " + (new Date()));
+        headers.put(ISSUE_PRIORITY_ID, 1);
+
+        template.sendBodyAndHeaders("Minha descrição jira " + (new Date()), 
headers);
+
+        Issue issue = issueRestClient.getIssue(backendIssue.getKey()).claim();
+        assertEquals(backendIssue, issue);
+        assertEquals(backendIssue.getIssueType(), issue.getIssueType());
+        assertEquals(backendIssue.getPriority(), issue.getPriority());
+        assertEquals(backendIssue.getSummary(), issue.getSummary());
+        assertEquals(backendIssue.getProject(), issue.getProject());
+        assertEquals(backendIssue.getDescription(), issue.getDescription());
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start")
+                            .to("jira://addIssue?jiraUrl=" + JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddWorkLogProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddWorkLogProducerTest.java
new file mode 100644
index 0000000..712bbb6
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AddWorkLogProducerTest.java
@@ -0,0 +1,251 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static org.apache.camel.component.jira.JiraConstants.MINUTES_SPENT;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssueWithComments;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssueWithWorkLogs;
+import static org.apache.camel.component.jira.springboot.test.Utils.newWorkLog;
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.apache.camel.test.junit5.TestSupport.assertStringContains;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.Worklog;
+import com.atlassian.jira.rest.client.api.domain.input.WorklogInput;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+import org.mockito.stubbing.Answer;
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        AddWorkLogProducerTest.class,
+        AddWorkLogProducerTest.TestConfiguration.class
+    }
+)
+
+public class AddWorkLogProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                backendIssue = createIssueWithComments(1, 1);
+                lenient().when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(backendIssue));
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void testAddWorkLog() throws InterruptedException {
+        int minutesSpent = 10;
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        headers.put(MINUTES_SPENT, minutesSpent);
+        String comment = "A new test comment " + new Date();
+
+        when(issueRestClient.addWorklog(any(URI.class), 
any(WorklogInput.class)))
+                .then((Answer<Void>) inv -> {
+                    Collection<Worklog> workLogs = new ArrayList<>();
+                    workLogs.add(newWorkLog(backendIssue.getId(), 
minutesSpent, comment));
+                    backendIssue = 
createIssueWithWorkLogs(backendIssue.getId(), workLogs);
+                    return null;
+                });
+
+        template.sendBodyAndHeaders(comment, headers);
+
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient).getIssue(backendIssue.getKey());
+        verify(issueRestClient).addWorklog(eq(backendIssue.getWorklogUri()), 
any(WorklogInput.class));
+    }
+    
+    @Test
+    public void testAddWorkLogMissingIssueKey() throws InterruptedException {
+        int minutesSpent = 3;
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(MINUTES_SPENT, minutesSpent);
+        String comment = "A new test comment " + new Date();
+
+        try {
+            template.sendBodyAndHeaders(comment, headers);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), ISSUE_KEY);
+        }
+        mockResult.reset();
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).getIssue(any(String.class));
+        verify(issueRestClient, never()).addWorklog(any(URI.class), 
any(WorklogInput.class));
+    }
+
+    @Test
+    public void testAddWorkLogMissingMinutesSpent() throws 
InterruptedException {
+        
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        String comment = "A new test comment " + new Date();
+
+        try {
+            template.sendBodyAndHeaders(comment, headers);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), MINUTES_SPENT);
+        }
+        
+        mockResult.reset();
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).getIssue(any(String.class));
+        verify(issueRestClient, never()).addWorklog(any(URI.class), 
any(WorklogInput.class));
+    }
+
+    @Test
+    public void testAddWorkLogMissingComment() throws InterruptedException {
+        int minutesSpent = 60;
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        headers.put(MINUTES_SPENT, minutesSpent);
+
+        try {
+            template.sendBodyAndHeaders(null, headers);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), "Missing exchange body");
+        }
+        mockResult.reset();
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).getIssue(any(String.class));
+        verify(issueRestClient, never()).addWorklog(any(URI.class), 
any(WorklogInput.class));
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                    .to("jira://addWorkLog?jiraUrl=" + JIRA_CREDENTIALS)
+                    .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AttachFileProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AttachFileProducerTest.java
new file mode 100644
index 0000000..7b15884
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/AttachFileProducerTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.KEY;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssueWithAttachment;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Attachment;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        AttachFileProducerTest.class,
+        AttachFileProducerTest.TestConfiguration.class
+    }
+)
+
+public class AttachFileProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static File attachedFile;
+    
+    static Issue issue;
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                when(issueRestClient.getIssue(any())).then(inv -> {
+                    if (issue == null) {
+                        issue = createIssue(1);
+                    }
+                    return Promises.promise(issue);
+                });
+                when(issueRestClient.addAttachments(any(URI.class), 
any(File.class))).then(inv -> {
+                    File attachedFileTmp = inv.getArgument(1);
+                    // create a temp destiny file as the attached file is 
marked for removal on AttachFileProducer
+                    attachedFile = File.createTempFile("camel-jira-test-", 
null);
+                    Files.copy(attachedFileTmp.toPath(), 
attachedFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+                    attachedFile.deleteOnExit();
+                    Collection<Attachment> attachments = new ArrayList<>();
+                    attachments.add(new Attachment(
+                            issue.getAttachmentsUri(), attachedFile.getName(), 
null, null,
+                            Long.valueOf(attachedFile.length()).intValue(), 
null, null, null));
+                    // re-create the issue with the attachment sent by the 
route
+                    issue = createIssueWithAttachment(issue.getId(), 
issue.getSummary(), issue.getKey(), issue.getIssueType(),
+                            issue.getDescription(), issue.getPriority(), 
issue.getAssignee(), attachments);
+                    return null;
+                });
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    private File generateSampleFile() throws IOException {
+        File sampleRandomFile = File.createTempFile("attach-test", null);
+        sampleRandomFile.deleteOnExit();
+        String text = "A random text to use on the AttachFileProducerTest.java 
of camel-jira component.";
+        Files.write(sampleRandomFile.toPath(), text.getBytes(), 
StandardOpenOption.CREATE);
+        return sampleRandomFile;
+    }
+    
+    @Test
+    public void verifyAttachment() throws InterruptedException, IOException {
+        template.sendBody(generateSampleFile());
+        Issue retrievedIssue = 
issueRestClient.getIssue(issue.getKey()).claim();
+        assertEquals(issue, retrievedIssue);
+        // there is only one attachment
+        Attachment attachFile = 
retrievedIssue.getAttachments().iterator().next();
+        assertEquals(attachFile.getFilename(), attachedFile.getName());
+        assertEquals(attachFile.getSize(), attachedFile.length());
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start")
+                            .setHeader(ISSUE_KEY, () -> KEY + "-1")
+                            .to("jira://attach?jiraUrl=" + JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/DeleteIssueProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/DeleteIssueProducerTest.java
new file mode 100644
index 0000000..d4c5a6d
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/DeleteIssueProducerTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.KEY;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        DeleteIssueProducerTest.class,
+        DeleteIssueProducerTest.TestConfiguration.class
+    }
+)
+
+public class DeleteIssueProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    static Issue issue;
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                issue = createIssue(1);
+                when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(issue));
+                when(issueRestClient.deleteIssue(anyString(), 
anyBoolean())).then(inv -> {
+                    issue = null;
+                    return null;
+                });
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void verifyDeleteIssue() throws InterruptedException {
+        String issueKey = issue.getKey();
+        template.sendBody(null);
+        Issue retrievedIssue = issueRestClient.getIssue(issueKey).claim();
+        assertNull(retrievedIssue);
+        assertEquals(issue, retrievedIssue);
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws IOException {
+                    from("direct:start")
+                            .setHeader(ISSUE_KEY, () -> KEY + "-1")
+                            .to("jira://deleteIssue?jiraUrl=" + 
JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/FetchCommentsProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/FetchCommentsProducerTest.java
new file mode 100644
index 0000000..97fbaae
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/FetchCommentsProducerTest.java
@@ -0,0 +1,177 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.apache.camel.test.junit5.TestSupport.assertStringContains;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        FetchCommentsProducerTest.class,
+        FetchCommentsProducerTest.TestConfiguration.class
+    }
+)
+
+public class FetchCommentsProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                backendIssue = mock(Issue.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void testFetchComments() throws InterruptedException {
+        when(backendIssue.getKey()).thenReturn("TEST-123");
+        when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(backendIssue));
+
+        template.sendBodyAndHeader(null, ISSUE_KEY, backendIssue.getKey());
+
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient).getIssue(backendIssue.getKey());
+        verify(backendIssue).getComments();
+    }
+
+    @Test
+    public void testFetchCommentsMissingIssueKey() throws InterruptedException 
{
+        try {
+            template.sendBody(null);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), ISSUE_KEY);
+        }
+
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).getIssue(backendIssue.getKey());
+        verify(backendIssue, never()).getComments();
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start")
+                            .to("jira://fetchComments?jiraUrl=" + 
JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/FetchIssueProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/FetchIssueProducerTest.java
new file mode 100644
index 0000000..88b991f
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/FetchIssueProducerTest.java
@@ -0,0 +1,174 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static org.apache.camel.test.junit5.TestSupport.assertIsInstanceOf;
+import static org.apache.camel.test.junit5.TestSupport.assertStringContains;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.fail;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        FetchIssueProducerTest.class,
+        FetchIssueProducerTest.TestConfiguration.class
+    }
+)
+
+public class FetchIssueProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                backendIssue = mock(Issue.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void testFetchIssue() throws InterruptedException {
+        when(backendIssue.getKey()).thenReturn("TEST-123");
+        when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(backendIssue));
+
+        template.sendBodyAndHeader(null, ISSUE_KEY, backendIssue.getKey());
+
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient).getIssue(backendIssue.getKey());
+    }
+
+    @Test
+    public void testFetchIssueMissingIssueKey() throws InterruptedException {
+        try {
+            template.sendBody(null);
+            fail("Should have thrown an exception");
+        } catch (CamelExecutionException e) {
+            IllegalArgumentException cause = 
assertIsInstanceOf(IllegalArgumentException.class, e.getCause());
+            assertStringContains(cause.getMessage(), ISSUE_KEY);
+        }
+
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+
+        verify(issueRestClient, never()).getIssue(backendIssue.getKey());
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws Exception {
+                    from("direct:start")
+                    .to("jira://fetchIssue?jiraUrl=" + JIRA_CREDENTIALS)
+                    .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/JiraTestConstants.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/JiraTestConstants.java
new file mode 100644
index 0000000..a21e135
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/JiraTestConstants.java
@@ -0,0 +1,28 @@
+/*
+ * 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.jira.springboot.test;
+
+public interface JiraTestConstants {
+
+    String KEY = "TST";
+    String TEST_JIRA_URL = "https://somerepo.atlassian.net";;
+    String PROJECT = "TST";
+    String USERNAME = "someguy";
+    String PASSWORD = "my_password";
+    String JIRA_CREDENTIALS = TEST_JIRA_URL + "&username=" + USERNAME + 
"&password=" + PASSWORD;
+    String WATCHED_COMPONENTS = "Priority,Status,Resolution";
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/NewCommentsConsumerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/NewCommentsConsumerTest.java
new file mode 100644
index 0000000..a814c2f
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/NewCommentsConsumerTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.jira.springboot.test;
+
+
+
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssueWithComments;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.PROJECT;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.SearchRestClient;
+import com.atlassian.jira.rest.client.api.domain.Comment;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.SearchResult;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+
+import io.atlassian.util.concurrent.Promise;
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        NewCommentsConsumerTest.class,
+        NewCommentsConsumerTest.TestConfiguration.class
+    }
+)
+
+public class NewCommentsConsumerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+    
+    static SearchRestClient searchRestClient;
+
+    static List<Issue> issues = new ArrayList<>();
+  
+       
+    @BeforeAll
+    public static void beforeAll() {
+        issues.add(createIssueWithComments(1L, 1));
+        issues.add(createIssueWithComments(2L, 1));
+        issues.add(createIssueWithComments(3L, 1));
+    }
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                searchRestClient = mock(SearchRestClient.class);
+                SearchResult result = new SearchResult(0, 50, 100, issues);
+                Promise<SearchResult> promiseSearchResult = 
Promises.promise(result);
+                Issue issue = createIssueWithComments(4L, 1);
+                Promise<Issue> promiseIssue = Promises.promise(issue);
+
+                
when(jiraClient.getSearchClient()).thenReturn(searchRestClient);
+                when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+                
when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), any(), 
any())).thenReturn(jiraClient);
+                when(searchRestClient.searchJql(any(), any(), any(), 
any())).thenReturn(promiseSearchResult);
+                
when(issueRestClient.getIssue(anyString())).thenReturn(promiseIssue);
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void emptyAtStartupTest() throws Exception {
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void singleIssueCommentsTest() throws Exception {
+        Issue issueWithCommends = createIssueWithComments(11L, 3000);
+        Issue issueWithNoComments = createIssue(51L);
+
+        reset(issueRestClient);
+        AtomicInteger regulator = new AtomicInteger();
+        when(issueRestClient.getIssue(anyString())).then(inv -> {
+            int idx = regulator.getAndIncrement();
+            Issue issue = issueWithNoComments;
+            if (idx < 1) {
+                issue = issueWithCommends;
+            }
+            return Promises.promise(issue);
+        });
+        List<Comment> comments = new ArrayList<>();
+        for (Comment c : issueWithCommends.getComments()) {
+            comments.add(c);
+        }
+        // reverse the order, from oldest comment to recent
+        Collections.reverse(comments);
+        // expect 3000 comments
+        mockResult.expectedBodiesReceived(comments);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void multipleIssuesTest() throws Exception {
+        Issue issue1 = createIssueWithComments(20L, 2000);
+        Issue issue2 = createIssueWithComments(21L, 3000);
+        Issue issue3 = createIssueWithComments(22L, 1000);
+        List<Issue> newIssues = new ArrayList<>();
+        newIssues.add(issue1);
+        newIssues.add(issue2);
+        newIssues.add(issue3);
+        Issue issueWithNoComments = createIssue(31L);
+
+        reset(searchRestClient);
+        reset(issueRestClient);
+        SearchResult searchResult = new SearchResult(0, 50, 3, newIssues);
+        Promise<SearchResult> searchResultPromise = 
Promises.promise(searchResult);
+        when(searchRestClient.searchJql(anyString(), any(), any(), 
any())).thenReturn(searchResultPromise);
+        AtomicInteger regulator = new AtomicInteger();
+        when(issueRestClient.getIssue(anyString())).then(inv -> {
+            int idx = regulator.getAndIncrement();
+            Issue issue = issueWithNoComments;
+            if (idx < newIssues.size()) {
+                issue = newIssues.get(idx);
+            }
+            return Promises.promise(issue);
+        });
+        List<Comment> comments = new ArrayList<>();
+        for (Issue issue : newIssues) {
+            for (Comment c : issue.getComments()) {
+                comments.add(c);
+            }
+        }
+        // reverse the order, from oldest comment to recent
+        Collections.reverse(comments);
+        // expect 6000 comments
+        mockResult.expectedBodiesReceived(comments);
+        mockResult.assertIsSatisfied();
+    }
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("jira://newComments?jiraUrl=" + JIRA_CREDENTIALS + 
"&jql=project=" + PROJECT + "&delay=1000")
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/NewIssuesConsumerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/NewIssuesConsumerTest.java
new file mode 100644
index 0000000..69acd3b
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/NewIssuesConsumerTest.java
@@ -0,0 +1,205 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.PROJECT;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.SearchRestClient;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.SearchResult;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+
+import io.atlassian.util.concurrent.Promise;
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        NewIssuesConsumerTest.class,
+        NewIssuesConsumerTest.TestConfiguration.class
+    }
+)
+
+public class NewIssuesConsumerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static SearchRestClient searchRestClient;
+    
+    static List<Issue> issues = new ArrayList<>();
+    
+    @BeforeAll
+    public static void beforeAll() {
+        issues.add(createIssue(1L));
+        issues.add(createIssue(2L));
+        issues.add(createIssue(3L));
+    }
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                searchRestClient = mock(SearchRestClient.class);
+                SearchResult result = new SearchResult(0, 50, 100, issues);
+                Promise<SearchResult> promiseSearchResult = 
Promises.promise(result);
+
+                
when(jiraClient.getSearchClient()).thenReturn(searchRestClient);
+                
when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), any(), 
any())).thenReturn(jiraClient);
+                when(searchRestClient.searchJql(any(), any(), any(), 
any())).thenReturn(promiseSearchResult);
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void emptyAtStartupTest() throws Exception {
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void singleIssueTest() throws Exception {
+        Issue issue = createIssue(11);
+
+        reset(searchRestClient);
+        AtomicBoolean searched = new AtomicBoolean();
+        when(searchRestClient.searchJql(any(), any(), any(), 
any())).then(invocation -> {
+            List<Issue> newIissues = new ArrayList<>();
+            if (!searched.get()) {
+                newIissues.add(issue);
+                searched.set(true);
+            }
+            SearchResult result = new SearchResult(0, 50, 100, newIissues);
+            return Promises.promise(result);
+        });
+        mockResult.expectedBodiesReceived(issue);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void multipleIssuesTest() throws Exception {
+        Issue issue1 = createIssue(21);
+        Issue issue2 = createIssue(22);
+        Issue issue3 = createIssue(23);
+
+        reset(searchRestClient);
+        AtomicBoolean searched = new AtomicBoolean();
+        when(searchRestClient.searchJql(any(), any(), any(), 
any())).then(invocation -> {
+            List<Issue> newIssues = new ArrayList<>();
+            if (!searched.get()) {
+                newIssues.add(issue1);
+                newIssues.add(issue2);
+                newIssues.add(issue3);
+                searched.set(true);
+            }
+            SearchResult result = new SearchResult(0, 50, 3, newIssues);
+            return Promises.promise(result);
+        });
+
+        mockResult.expectedBodiesReceived(issue3, issue2, issue1);
+        mockResult.assertIsSatisfied();
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("jira://newIssues?jiraUrl=" + JIRA_CREDENTIALS + 
"&jql=project=" + PROJECT + "&delay=5000")
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/TransitionIssueProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/TransitionIssueProducerTest.java
new file mode 100644
index 0000000..71e092e
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/TransitionIssueProducerTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.ISSUE_TRANSITION_ID;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.TEST_JIRA_URL;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.transitionIssueDone;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.KEY;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.URI;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.Resolution;
+import com.atlassian.jira.rest.client.api.domain.Status;
+import com.atlassian.jira.rest.client.api.domain.input.TransitionInput;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        TransitionIssueProducerTest.class,
+        TransitionIssueProducerTest.TestConfiguration.class
+    }
+)
+
+public class TransitionIssueProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    static Issue issue;
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                issue = createIssue(1);
+                when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(issue));
+                when(issueRestClient.transition(any(Issue.class), 
any(TransitionInput.class))).then(inv -> {
+                    URI doneStatusUri = URI.create(TEST_JIRA_URL + 
"/rest/api/2/status/1");
+                    URI doneResolutionUri = URI.create(TEST_JIRA_URL + 
"/rest/api/2/resolution/1");
+                    Status status = new Status(doneStatusUri, 1L, "Done", 
"Done", null, null);
+                    Resolution resolution = new Resolution(doneResolutionUri, 
1L, "Resolution", "Resolution");
+                    issue = transitionIssueDone(issue, status, resolution);
+                    return null;
+                });
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void verifyTransition() throws InterruptedException {
+        template.sendBody(null);
+        Issue retrievedIssue = 
issueRestClient.getIssue(issue.getKey()).claim();
+        assertEquals(issue, retrievedIssue);
+        assertEquals(issue.getStatus(), retrievedIssue.getStatus());
+        assertEquals(issue.getResolution(), retrievedIssue.getResolution());
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() throws IOException {
+                    from("direct:start")
+                            .setHeader(ISSUE_KEY, () -> KEY + "-1")
+                            .setHeader(ISSUE_TRANSITION_ID, () -> 31)
+                            .to("jira://transitionIssue?jiraUrl=" + 
JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/UpdateIssueProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/UpdateIssueProducerTest.java
new file mode 100644
index 0000000..ae736ff
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/UpdateIssueProducerTest.java
@@ -0,0 +1,216 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_ASSIGNEE;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static 
org.apache.camel.component.jira.JiraConstants.ISSUE_PRIORITY_NAME;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_SUMMARY;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_TYPE_NAME;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.userAssignee;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.MetadataRestClient;
+import com.atlassian.jira.rest.client.api.domain.BasicIssue;
+import com.atlassian.jira.rest.client.api.domain.BasicPriority;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.IssueType;
+import com.atlassian.jira.rest.client.api.domain.Priority;
+import 
com.atlassian.jira.rest.client.api.domain.input.ComplexIssueInputFieldValue;
+import com.atlassian.jira.rest.client.api.domain.input.IssueInput;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import io.atlassian.util.concurrent.Promise;
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        UpdateIssueProducerTest.class,
+        UpdateIssueProducerTest.TestConfiguration.class
+    }
+)
+
+public class UpdateIssueProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+    
+    static MetadataRestClient metadataRestClient;
+
+    static Issue backendIssue;
+    
+        
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                metadataRestClient = mock(MetadataRestClient.class);
+                
when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), any(), 
any())).thenReturn(jiraClient);
+                when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+                
when(jiraClient.getMetadataClient()).thenReturn(metadataRestClient);
+                
+                Map<Integer, IssueType> issueTypes = new HashMap<>();
+                issueTypes.put(1, new IssueType(null, 1L, "Bug", false, null, 
null));
+                issueTypes.put(2, new IssueType(null, 2L, "Task", false, null, 
null));
+                Promise<Iterable<IssueType>> promiseIssueTypes = 
Promises.promise(issueTypes.values());
+                
when(metadataRestClient.getIssueTypes()).thenReturn(promiseIssueTypes);
+
+                Map<Integer, Priority> issuePriorities = new HashMap<>();
+                issuePriorities.put(1, new Priority(null, 1L, "High", null, 
null, null));
+                issuePriorities.put(2, new Priority(null, 2L, "Low", null, 
null, null));
+                Promise<Iterable<Priority>> promisePriorities = 
Promises.promise(issuePriorities.values());
+                
when(metadataRestClient.getPriorities()).thenReturn(promisePriorities);
+
+                backendIssue = createIssue(11L);
+                when(issueRestClient.updateIssue(anyString(), 
any(IssueInput.class))).then(inv -> {
+                    String issueKey = inv.getArgument(0);
+                    IssueInput issueInput = inv.getArgument(1);
+                    String summary = (String) 
issueInput.getField("summary").getValue();
+                    Integer issueTypeId = 
Integer.parseInt(getValue(issueInput, "issuetype", "id"));
+                    IssueType issueType = issueTypes.get(issueTypeId);
+                    String description = (String) 
issueInput.getField("description").getValue();
+                    Integer priorityId = Integer.parseInt(getValue(issueInput, 
"priority", "id"));
+                    BasicPriority priority = issuePriorities.get(priorityId);
+                    backendIssue = createIssue(11L, summary, issueKey, 
issueType, description, priority, userAssignee, null, null);
+                    BasicIssue basicIssue = new 
BasicIssue(backendIssue.getSelf(), backendIssue.getKey(), backendIssue.getId());
+                    return Promises.promise(basicIssue);
+                });
+                when(issueRestClient.getIssue(any())).then(inv -> 
Promises.promise(backendIssue));
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void verifyIssueUpdated() throws InterruptedException {
+
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        headers.put(ISSUE_TYPE_NAME, "Task");
+        headers.put(ISSUE_SUMMARY, "Demo Bug jira " + (new Date()));
+        headers.put(ISSUE_PRIORITY_NAME, "Low");
+        headers.put(ISSUE_ASSIGNEE, "tom");
+
+        template.sendBodyAndHeaders("New description " + (new Date()), 
headers);
+
+        Issue issue = issueRestClient.getIssue(backendIssue.getKey()).claim();
+        assertEquals(backendIssue, issue);
+        assertEquals(backendIssue.getIssueType(), issue.getIssueType());
+        assertEquals(backendIssue.getPriority(), issue.getPriority());
+        assertEquals(backendIssue.getSummary(), issue.getSummary());
+        assertEquals(backendIssue.getProject(), issue.getProject());
+        assertEquals(backendIssue.getDescription(), issue.getDescription());
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+    
+    private String getValue(IssueInput issueInput, String field, String key) {
+        ComplexIssueInputFieldValue complexField = 
(ComplexIssueInputFieldValue) issueInput.getField(field).getValue();
+        return (String) complexField.getValuesMap().get(key);
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start")
+                            .to("jira://updateIssue?jiraUrl=" + 
JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/Utils.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/Utils.java
new file mode 100644
index 0000000..a26af43
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/Utils.java
@@ -0,0 +1,194 @@
+/*
+ * 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.jira.springboot.test;
+
+import java.net.URI;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+import com.atlassian.jira.rest.client.api.StatusCategory;
+import com.atlassian.jira.rest.client.api.domain.Attachment;
+import com.atlassian.jira.rest.client.api.domain.BasicComponent;
+import com.atlassian.jira.rest.client.api.domain.BasicPriority;
+import com.atlassian.jira.rest.client.api.domain.BasicWatchers;
+import com.atlassian.jira.rest.client.api.domain.Comment;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.IssueLink;
+import com.atlassian.jira.rest.client.api.domain.IssueLinkType;
+import com.atlassian.jira.rest.client.api.domain.IssueType;
+import com.atlassian.jira.rest.client.api.domain.Priority;
+import com.atlassian.jira.rest.client.api.domain.Resolution;
+import com.atlassian.jira.rest.client.api.domain.Status;
+import com.atlassian.jira.rest.client.api.domain.User;
+import com.atlassian.jira.rest.client.api.domain.Worklog;
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.slf4j.LoggerFactory;
+
+import static com.atlassian.jira.rest.client.api.domain.User.S48_48;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.KEY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.TEST_JIRA_URL;
+
+public final class Utils {
+    public static User userAssignee;
+    static {
+        try {
+            userAssignee = new User(
+                    null, "user-test", "User Test", "user@test", true, null, 
buildUserAvatarUris("user-test", 10082L), null);
+        } catch (Exception e) {
+
+            LoggerFactory.getLogger(Utils.class).debug("Failed to build test 
user: {}", e.getMessage(), e);
+        }
+    }
+    private static IssueType issueType = new IssueType(null, 1L, "Bug", false, 
"Bug", null);
+
+    private Utils() {
+    }
+
+    public static Issue createIssue(long id) {
+        return createIssueWithComments(id, 0);
+    }
+
+    public static Issue createIssue(
+            long id, String summary, String key, IssueType issueType, String 
description,
+            BasicPriority priority, User assignee, Collection<BasicComponent> 
components, BasicWatchers watchers) {
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
id);
+        return new Issue(
+                summary, selfUri, KEY + "-" + id, id, null, issueType, null, 
description, priority, null, null, null,
+                assignee, null, null, null, null, null, components, null, 
null, null, null, null, null, null, watchers,
+                null, null, null, null, null);
+    }
+
+    public static Issue transitionIssueDone(Issue issue, Status status, 
Resolution resolution) {
+        return new Issue(
+                issue.getSummary(), issue.getSelf(), issue.getKey(), 
issue.getId(), null, issue.getIssueType(),
+                status, issue.getDescription(), issue.getPriority(), 
resolution, null, null,
+                issue.getAssignee(), null, null, null, null, null, null, null, 
null, null, null, null, null, null, null,
+                null, null, null, null, null);
+    }
+
+    public static Issue setPriority(Issue issue, Priority p) {
+        return new Issue(
+                issue.getSummary(), issue.getSelf(), issue.getKey(), 
issue.getId(), null, issue.getIssueType(),
+                issue.getStatus(), issue.getDescription(), p, 
issue.getResolution(), null, null,
+                issue.getAssignee(), null, null, null, null, null, null, null, 
null, null, null, null, null, null, null,
+                null, null, null, null, null);
+    }
+
+    public static Issue transitionIssueDone(Issue issue) {
+        URI doneStatusUri = URI.create(TEST_JIRA_URL + "/rest/api/2/status/1");
+        URI doneResolutionUri = URI.create(TEST_JIRA_URL + 
"/rest/api/2/resolution/1");
+        StatusCategory sc = new StatusCategory(doneResolutionUri, 
"statusCategory", 1L, "SC-1", "GREEN");
+        Status status = new Status(doneStatusUri, 1L, "Done", "Done", null, 
sc);
+        Resolution resolution = new Resolution(doneResolutionUri, 5L, 
"Resolution", "Resolution");
+        return transitionIssueDone(issue, status, resolution);
+    }
+
+    public static Issue createIssueWithAttachment(
+            long id, String summary, String key, IssueType issueType, String 
description,
+            BasicPriority priority, User assignee, Collection<Attachment> 
attachments) {
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
id);
+        return new Issue(
+                summary, selfUri, KEY + "-" + id, id, null, issueType, null, 
description, priority, null, attachments, null,
+                assignee, null, null, null, null, null, null, null, null, 
null, null, null, null, null, null,
+                null, null, null, null, null);
+    }
+
+    public static Issue createIssueWithComments(long id, int numComments) {
+        Collection<Comment> comments = new ArrayList<>();
+        if (numComments > 0) {
+            for (int idx = 1; idx < numComments + 1; idx++) {
+                Comment c = newComment(id, idx, "A test comment " + idx + " 
for " + KEY + "-" + id);
+                comments.add(c);
+            }
+        }
+        return createIssueWithComments(id, comments);
+    }
+
+    public static Issue createIssueWithComments(long id, Collection<Comment> 
comments) {
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
id);
+        return new Issue(
+                "jira summary test " + id, selfUri, KEY + "-" + id, id, null, 
issueType, null, "Description " + id,
+                null, null, null, null, userAssignee, null, null, null, null, 
null, null, null, null, comments, null, null,
+                null, null, null, null, null, null, null, null);
+    }
+
+    public static Issue createIssueWithLinks(long id, Collection<IssueLink> 
issueLinks) {
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
id);
+        return new Issue(
+                "jira summary test " + id, selfUri, KEY + "-" + id, id, null, 
issueType, null, "Description " + id,
+                null, null, null, null, userAssignee, null, null, null, null, 
null, null, null, null, null, null, issueLinks,
+                null, null, null, null, null, null, null, null);
+    }
+
+    public static Issue createIssueWithWorkLogs(long id, Collection<Worklog> 
worklogs) {
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
id);
+        return new Issue(
+                "jira summary test " + id, selfUri, KEY + "-" + id, id, null, 
issueType, null, "Description " + id,
+                null, null, null, null, userAssignee, null, null, null, null, 
null, null, null, null, null, null, null,
+                null, worklogs, null, null, null, null, null, null);
+    }
+
+    public static Comment newComment(long issueId, int newCommentId, String 
comment) {
+        DateTime now = DateTime.now();
+        long id = Long.parseLong(issueId + "0" + newCommentId);
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
issueId + "/comment");
+        return new Comment(selfUri, comment, null, null, now, null, null, id);
+    }
+
+    public static IssueLink newIssueLink(long issueId, int newLinkId, String 
comment) {
+        long id = Long.parseLong(issueId + "0" + newLinkId);
+        URI issueUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
id);
+        IssueLinkType relatesTo = new IssueLinkType("Relates", "relates to", 
IssueLinkType.Direction.OUTBOUND);
+
+        return new IssueLink(KEY, issueUri, relatesTo);
+    }
+
+    public static Worklog newWorkLog(long issueId, Integer minutesSpent, 
String comment) {
+        DateTime now = DateTime.now();
+        URI issueUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
issueId);
+        URI selfUri = URI.create(TEST_JIRA_URL + "/rest/api/latest/issue/" + 
issueId + "/comment");
+
+        return new Worklog(selfUri, issueUri, null, null, comment, now, null, 
null, minutesSpent, null);
+    }
+
+    private static Map<String, URI> buildUserAvatarUris(String user, Long 
avatarId) throws Exception {
+        final ImmutableMap.Builder<String, URI> builder = 
ImmutableMap.builder();
+        builder.put(S48_48, buildUserAvatarUri(user, avatarId));
+        return builder.build();
+    }
+
+    private static URI buildUserAvatarUri(String userName, Long avatarId) 
throws Exception {
+        // secure/useravatar?size=small&ownerId=admin&avatarId=10054
+        final StringBuilder sb = new StringBuilder("secure/useravatar?");
+
+        // Optional user name
+        if (StringUtils.isNotBlank(userName)) {
+            sb.append("ownerId=").append(userName).append("&");
+        }
+
+        // avatar Id
+        sb.append("avatarId=").append(avatarId);
+        String relativeAvatarUrl = sb.toString();
+        URI avatarUrl = new URL(TEST_JIRA_URL + "/" + 
relativeAvatarUrl).toURI();
+        return avatarUrl;
+    }
+
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/WatchUpdatesConsumerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/WatchUpdatesConsumerTest.java
new file mode 100644
index 0000000..cdb6a70
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/WatchUpdatesConsumerTest.java
@@ -0,0 +1,220 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.PROJECT;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.WATCHED_COMPONENTS;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.setPriority;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.transitionIssueDone;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.SearchRestClient;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.Priority;
+import com.atlassian.jira.rest.client.api.domain.SearchResult;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.jira.JiraConstants;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+
+import io.atlassian.util.concurrent.Promise;
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        WatchUpdatesConsumerTest.class,
+        WatchUpdatesConsumerTest.TestConfiguration.class
+    }
+)
+
+public class WatchUpdatesConsumerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+    
+    static SearchRestClient searchRestClient;
+    
+    static List<Issue> issues = new ArrayList<>();
+    
+    @BeforeAll
+    public static void beforeAll() {
+        issues.clear();
+        issues.add(createIssue(1L));
+        issues.add(createIssue(2L));
+        issues.add(createIssue(3L));
+    }
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                searchRestClient = mock(SearchRestClient.class);
+                SearchResult result = new SearchResult(0, 50, 100, issues);
+                Promise<SearchResult> promiseSearchResult = 
Promises.promise(result);
+
+                
when(jiraClient.getSearchClient()).thenReturn(searchRestClient);
+                
when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), any(), 
any())).thenReturn(jiraClient);
+                when(searchRestClient.searchJql(any(), any(), any(), 
any())).thenReturn(promiseSearchResult);
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void emptyAtStartupTest() throws Exception {
+        mockResult.expectedMessageCount(0);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void singleChangeTest() throws Exception {
+        Issue issue = setPriority(issues.get(0), new Priority(
+                null, 4L, "High", null, null, null));
+        reset(searchRestClient);
+        AtomicBoolean searched = new AtomicBoolean();
+        when(searchRestClient.searchJql(any(), any(), any(), 
any())).then(invocation -> {
+
+            if (!searched.get()) {
+                issues.remove(0);
+                issues.add(0, issue);
+            }
+            SearchResult result = new SearchResult(0, 50, 100, issues);
+            return Promises.promise(result);
+        });
+
+        mockResult.expectedBodiesReceived(issue.getPriority());
+        mockResult.expectedHeaderReceived(JiraConstants.ISSUE_CHANGED, 
"Priority");
+        mockResult.expectedHeaderReceived(JiraConstants.ISSUE_KEY, "TST-1");
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied(0);
+    }
+
+    @Test
+    public void multipleChangesWithAddedNewIssueTest() throws Exception {
+        final Issue issue = transitionIssueDone(issues.get(1));
+        final Issue issue2 = setPriority(issues.get(2), new Priority(
+                null, 4L, "High", null, null, null));
+
+        reset(searchRestClient);
+        AtomicBoolean searched = new AtomicBoolean();
+        when(searchRestClient.searchJql(any(), any(), any(), 
any())).then(invocation -> {
+            if (!searched.get()) {
+                issues.add(createIssue(4L));
+                issues.remove(1);
+                issues.add(1, issue);
+                issues.remove(2);
+                issues.add(2, issue2);
+                searched.set(true);
+            }
+
+            SearchResult result = new SearchResult(0, 50, 3, issues);
+            return Promises.promise(result);
+        });
+
+        mockResult.expectedMessageCount(3);
+        mockResult.expectedBodiesReceivedInAnyOrder(issue.getStatus(), 
issue.getResolution(), issue2.getPriority());
+        mockResult.assertIsSatisfied(1000);
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("jira://watchUpdates?jiraUrl=" + JIRA_CREDENTIALS
+                         + "&jql=project=" + PROJECT + 
"&delay=5000&watchedFields=" + WATCHED_COMPONENTS)
+                                 .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}
diff --git 
a/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/WatcherProducerTest.java
 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/WatcherProducerTest.java
new file mode 100644
index 0000000..5fe8fc4
--- /dev/null
+++ 
b/components-starter/camel-jira-starter/src/test/java/org/apache/camel/component/jira/springboot/test/WatcherProducerTest.java
@@ -0,0 +1,264 @@
+/*
+ * 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.jira.springboot.test;
+
+
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_KEY;
+import static org.apache.camel.component.jira.JiraConstants.ISSUE_WATCHERS_ADD;
+import static 
org.apache.camel.component.jira.JiraConstants.ISSUE_WATCHERS_REMOVE;
+import static 
org.apache.camel.component.jira.JiraConstants.JIRA_REST_CLIENT_FACTORY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.JIRA_CREDENTIALS;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.KEY;
+import static 
org.apache.camel.component.jira.springboot.test.JiraTestConstants.TEST_JIRA_URL;
+import static 
org.apache.camel.component.jira.springboot.test.Utils.createIssue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.mock;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.atlassian.jira.rest.client.api.IssueRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClient;
+import com.atlassian.jira.rest.client.api.JiraRestClientFactory;
+import com.atlassian.jira.rest.client.api.domain.BasicUser;
+import com.atlassian.jira.rest.client.api.domain.BasicWatchers;
+import com.atlassian.jira.rest.client.api.domain.Issue;
+import com.atlassian.jira.rest.client.api.domain.Watchers;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.spring.boot.CamelContextConfiguration;
+import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import io.atlassian.util.concurrent.Promises;
+
+import org.springframework.beans.factory.annotation.Autowired;
+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.springframework.test.annotation.DirtiesContext.ClassMode;
+
+
+
+@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
+@CamelSpringBootTest
+@SpringBootTest(
+    classes = {
+        CamelAutoConfiguration.class,
+        WatcherProducerTest.class,
+        WatcherProducerTest.TestConfiguration.class
+    }
+)
+
+public class WatcherProducerTest {
+
+    @Autowired
+    private CamelContext camelContext;
+    
+
+    
+    @Autowired
+    @Produce("direct:start")
+    ProducerTemplate template;
+
+    @EndpointInject("mock:result")
+    MockEndpoint mockResult;
+    
+    static JiraRestClient jiraClient;
+    
+    static JiraRestClientFactory jiraRestClientFactory;
+    
+    static IssueRestClient issueRestClient;
+
+    static Issue backendIssue;
+    
+    static Issue issue;
+    
+    static List<String> backendwatchers = new ArrayList<>();
+    
+    @Bean
+    CamelContextConfiguration contextConfiguration() {
+        return new CamelContextConfiguration() {
+            @Override
+            public void beforeApplicationStart(CamelContext context) {
+                //get chance to mock camelContext/Registry
+                jiraRestClientFactory = mock(JiraRestClientFactory.class);
+                jiraClient = mock(JiraRestClient.class);
+                issueRestClient = mock(IssueRestClient.class);
+                
lenient().when(jiraRestClientFactory.createWithBasicHttpAuthentication(any(), 
any(), any())).thenReturn(jiraClient);
+                
lenient().when(jiraClient.getIssueClient()).thenReturn(issueRestClient);
+
+                backendwatchers.add("user1");
+                backendwatchers.add("user2");
+                backendwatchers.add("user3");
+                backendwatchers.add("user4");
+                backendwatchers.add("user5");
+                URI watchersUri = URI.create(TEST_JIRA_URL + 
"/rest/api/2/backendIssue/" + KEY + "-11/backendwatchers");
+                BasicWatchers initialBasicWatchers = new 
BasicWatchers(watchersUri, true, backendwatchers.size());
+                backendIssue
+                        = createIssue(11L, "Test backendIssue", KEY + "-" + 
11, null, null, null, null, null, initialBasicWatchers);
+                lenient().when(issueRestClient.addWatcher(any(URI.class), 
anyString())).then(inv -> {
+                    String username = inv.getArgument(1);
+                    backendwatchers.add(username);
+                    BasicWatchers basicWatchers = new 
BasicWatchers(watchersUri, true, backendwatchers.size());
+                    backendIssue = createIssue(backendIssue.getId(), 
backendIssue.getSummary(), backendIssue.getKey(),
+                            backendIssue.getIssueType(), 
backendIssue.getDescription(),
+                            backendIssue.getPriority(), 
backendIssue.getAssignee(), null, basicWatchers);
+                    return null;
+                });
+                lenient().when(issueRestClient.removeWatcher(any(URI.class), 
anyString())).then(inv -> {
+                    String username = inv.getArgument(1);
+                    backendwatchers.remove(username);
+                    BasicWatchers basicWatchers = new 
BasicWatchers(watchersUri, true, backendwatchers.size());
+                    backendIssue = createIssue(backendIssue.getId(), 
backendIssue.getSummary(), backendIssue.getKey(),
+                            backendIssue.getIssueType(), 
backendIssue.getDescription(),
+                            backendIssue.getPriority(), 
backendIssue.getAssignee(), null, basicWatchers);
+                    return null;
+                });
+                lenient().when(issueRestClient.getIssue(anyString())).then(inv 
-> Promises.promise(backendIssue));
+                
lenient().when(issueRestClient.getWatchers(any(URI.class))).then(inv -> {
+                    Collection<BasicUser> users = new ArrayList<>();
+                    for (String watcher : backendwatchers) {
+                        users.add(new BasicUser(null, watcher, watcher));
+                    }
+                    BasicWatchers basicWatchers = new 
BasicWatchers(watchersUri, true, users.size());
+                    Watchers watchers = new Watchers(basicWatchers, users);
+                    return Promises.promise(watchers);
+                });
+                
+                camelContext.getRegistry().bind(JIRA_REST_CLIENT_FACTORY, 
jiraRestClientFactory);
+            }
+
+            @Override
+            public void afterApplicationStart(CamelContext camelContext) {
+                //do nothing here                
+            }
+        };
+    }
+    
+    @Test
+    public void addWatchers() throws InterruptedException {
+        List<String> watchersToAdd = new ArrayList<>();
+        watchersToAdd.add("user1A");
+        watchersToAdd.add("user1B");
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        headers.put(ISSUE_WATCHERS_ADD, watchersToAdd);
+        template.sendBodyAndHeaders(null, headers);
+
+        Issue retrievedIssue = 
issueRestClient.getIssue(backendIssue.getKey()).claim();
+        assertEquals(backendIssue, retrievedIssue);
+        assertEquals(retrievedIssue.getWatchers().getNumWatchers(), 
backendwatchers.size());
+
+        Watchers watchers = 
issueRestClient.getWatchers(retrievedIssue.getWatchers().getSelf()).claim();
+        for (BasicUser user : watchers.getUsers()) {
+            assertTrue(backendwatchers.contains(user.getName()));
+        }
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void removeWatchers() throws InterruptedException {
+        List<String> watchersToRemove = new ArrayList<>();
+        watchersToRemove.add("user2");
+        watchersToRemove.add("user3");
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        headers.put(ISSUE_WATCHERS_REMOVE, watchersToRemove);
+        template.sendBodyAndHeaders(null, headers);
+
+        Issue retrievedIssue = 
issueRestClient.getIssue(backendIssue.getKey()).claim();
+        assertEquals(backendIssue, retrievedIssue);
+        assertEquals(retrievedIssue.getWatchers().getNumWatchers(), 
backendwatchers.size());
+
+        Watchers watchers = 
issueRestClient.getWatchers(retrievedIssue.getWatchers().getSelf()).claim();
+        for (BasicUser user : watchers.getUsers()) {
+            assertTrue(backendwatchers.contains(user.getName()));
+        }
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    @Test
+    public void addRemoveWatchers() throws InterruptedException {
+        List<String> watchersToAdd = new ArrayList<>();
+        watchersToAdd.add("user2A");
+        watchersToAdd.add("user2B");
+        List<String> watchersToRemove = new ArrayList<>();
+        watchersToRemove.add("user4");
+        watchersToRemove.add("user5");
+        Map<String, Object> headers = new HashMap<>();
+        headers.put(ISSUE_KEY, backendIssue.getKey());
+        headers.put(ISSUE_WATCHERS_ADD, watchersToAdd);
+        headers.put(ISSUE_WATCHERS_REMOVE, watchersToRemove);
+        template.sendBodyAndHeaders(null, headers);
+
+        Issue retrievedIssue = 
issueRestClient.getIssue(backendIssue.getKey()).claim();
+        assertEquals(backendIssue, retrievedIssue);
+        assertEquals(retrievedIssue.getWatchers().getNumWatchers(), 
backendwatchers.size());
+
+        Watchers watchers = 
issueRestClient.getWatchers(retrievedIssue.getWatchers().getSelf()).claim();
+        for (BasicUser user : watchers.getUsers()) {
+            assertTrue(backendwatchers.contains(user.getName()));
+        }
+        mockResult.expectedMessageCount(1);
+        mockResult.assertIsSatisfied();
+    }
+
+    
+    @Configuration
+    public class TestConfiguration {
+        
+        
+
+        @Bean
+        public RouteBuilder routeBuilder() {
+            return new RouteBuilder() {
+                @Override
+                public void configure() {
+                    from("direct:start")
+                            .to("jira://watchers?jiraUrl=" + JIRA_CREDENTIALS)
+                            .to(mockResult);
+                }
+            };
+        }
+        
+      
+    }
+    
+    
+    
+    
+}

Reply via email to