Add tests to JiraItsFacade

Passing the JiraClient dependency as parameter to the constructor
(instead of creating it inside the class) helps making this class
testable. In the same sense, the Jira configuration can be injected now
into the JiraClient; the previous constructor is kept, though, to allow
the init step to test connectivity. This will be modified in a follow up
change to avoid passing parameters along the whole chain of calls.

Change-Id: Iee6803aded52fff70e079630bed421748ee27d68
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
index 72c5acc..8fcdc60 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraClient.java
@@ -21,6 +21,7 @@
 import static java.net.HttpURLConnection.HTTP_OK;
 
 import com.google.gson.Gson;
+import com.google.inject.Inject;
 import com.googlesource.gerrit.plugins.its.base.its.InvalidTransitionException;
 import com.googlesource.gerrit.plugins.its.jira.restapi.JiraComment;
 import com.googlesource.gerrit.plugins.its.jira.restapi.JiraIssue;
@@ -42,12 +43,19 @@
   private final JiraRestApiProvider apiBuilder;
   private final Gson gson;
 
+  @Inject
+  public JiraClient(JiraConfig jiraConfig) throws MalformedURLException {
+    this(jiraConfig.getUrl(), jiraConfig.getUsername(), jiraConfig.getPassword());
+  }
+
   /**
+   * This constructor is kept to allow testing connectivity from the init class
+   *
    * @param url jira url
    * @param user username of the jira user
    * @param pass password of the jira user
    */
-  public JiraClient(String url, String user, String pass) throws MalformedURLException {
+  JiraClient(String url, String user, String pass) throws MalformedURLException {
     this.apiBuilder = new JiraRestApiProvider(url, user, pass);
     this.gson = new Gson();
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
index 790cefd..c14f2e6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacade.java
@@ -20,7 +20,6 @@
 import com.googlesource.gerrit.plugins.its.jira.restapi.JiraProject;
 import com.googlesource.gerrit.plugins.its.jira.restapi.JiraServerInfo;
 import java.io.IOException;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.concurrent.Callable;
 import org.slf4j.Logger;
@@ -32,18 +31,16 @@
 
   private Logger log = LoggerFactory.getLogger(JiraItsFacade.class);
 
-  private final JiraConfig jiraConfig;
-
-  private JiraClient client;
+  private final JiraClient jiraClient;
 
   @Inject
-  public JiraItsFacade(JiraConfig jiraConfig) {
-    this.jiraConfig = jiraConfig;
+  public JiraItsFacade(JiraClient jiraClient) {
+    this.jiraClient = jiraClient;
     try {
-      JiraServerInfo info = client().sysInfo();
+      JiraServerInfo info = this.jiraClient.sysInfo();
       log.info(
           "Connected to JIRA at {}, reported version is {}", info.getBaseUri(), info.getVersion());
-      for (JiraProject p : client().getProjects()) {
+      for (JiraProject p : this.jiraClient.getProjects()) {
         log.info("Found project: {} (key: {})", p.getName(), p.getKey());
       }
     } catch (Exception ex) {
@@ -57,9 +54,9 @@
     return execute(
         () -> {
           if (check.equals(Check.ACCESS)) {
-            return client().healthCheckAccess();
+            return jiraClient.healthCheckAccess();
           }
-          return client().healthCheckSysinfo();
+          return jiraClient.healthCheckSysinfo();
         });
   }
 
@@ -69,7 +66,7 @@
     execute(
         () -> {
           log.debug("Adding comment {} to issue {}", comment, issueKey);
-          client().addComment(issueKey, comment);
+          jiraClient.addComment(issueKey, comment);
           log.debug("Added comment {} to issue {}", comment, issueKey);
           return issueKey;
         });
@@ -96,7 +93,7 @@
   private void doPerformAction(String issueKey, String actionName)
       throws IOException, InvalidTransitionException {
     log.debug("Trying to perform action: {} on issue {}", actionName, issueKey);
-    boolean ret = client().doTransition(issueKey, actionName);
+    boolean ret = jiraClient.doTransition(issueKey, actionName);
     if (ret) {
       log.debug("Action {} successful on Issue {}", actionName, issueKey);
     } else {
@@ -106,18 +103,7 @@
 
   @Override
   public boolean exists(String issueKey) throws IOException {
-    return execute(() -> client().issueExists(issueKey));
-  }
-
-  private JiraClient client() throws MalformedURLException {
-    if (client == null) {
-      log.debug("Connecting to jira at {}", jiraConfig.getJiraUrl());
-      client =
-          new JiraClient(
-              jiraConfig.getJiraUrl(), jiraConfig.getUsername(), jiraConfig.getPassword());
-      log.debug("Authenticating as User {}", jiraConfig.getUsername());
-    }
-    return client;
+    return execute(() -> jiraClient.issueExists(issueKey));
   }
 
   private <P> P execute(Callable<P> function) throws IOException {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java
new file mode 100644
index 0000000..6d645c8
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/its/jira/JiraItsFacadeTest.java
@@ -0,0 +1,97 @@
+// Copyright (C) 2018 Android Open Source Project
+//
+// Licensed 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 com.googlesource.gerrit.plugins.its.jira;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.googlesource.gerrit.plugins.its.base.its.InvalidTransitionException;
+import com.googlesource.gerrit.plugins.its.base.its.ItsFacade.Check;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraProject;
+import com.googlesource.gerrit.plugins.its.jira.restapi.JiraServerInfo;
+import java.io.IOException;
+import java.net.URL;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JiraItsFacadeTest {
+
+  private static final String ACTION = "action";
+  private static final String COMMENT = "comment";
+  private static final String ISSUE_KEY = "issueKey";
+
+  @Mock private JiraClient jiraClient;
+
+  private JiraItsFacade jiraFacade;
+
+  @Before
+  public void setUp() throws Exception {
+    JiraServerInfo jiraServerInfo = mock(JiraServerInfo.class);
+    when(jiraServerInfo.getBaseUri()).thenReturn("http://jira-server.com");
+    when(jiraServerInfo.getVersion()).thenReturn("v1");
+    when(jiraClient.sysInfo()).thenReturn(jiraServerInfo);
+    JiraProject jiraProject = mock(JiraProject.class);
+    when(jiraProject.getKey()).thenReturn("key1");
+    when(jiraProject.getName()).thenReturn("testProject");
+    when(jiraClient.getProjects()).thenReturn(new JiraProject[] {jiraProject});
+  }
+
+  @Test
+  public void healthCheckAccess() throws IOException {
+    jiraFacade = new JiraItsFacade(jiraClient);
+    jiraFacade.healthCheck(Check.ACCESS);
+    verify(jiraClient).healthCheckAccess();
+  }
+
+  @Test
+  public void healthCheckSysInfo() throws IOException {
+    jiraFacade = new JiraItsFacade(jiraClient);
+    jiraFacade.healthCheck(Check.SYSINFO);
+    verify(jiraClient).healthCheckSysinfo();
+  }
+
+  @Test
+  public void addComment() throws IOException {
+    jiraFacade = new JiraItsFacade(jiraClient);
+    jiraFacade.addComment(ISSUE_KEY, COMMENT);
+    verify(jiraClient).addComment(ISSUE_KEY, COMMENT);
+  }
+
+  @Test
+  public void addRelatedLink() throws IOException {
+    jiraFacade = new JiraItsFacade(jiraClient);
+    jiraFacade.addRelatedLink(ISSUE_KEY, new URL("http://jira.com"), "description");
+    verify(jiraClient).addComment(ISSUE_KEY, "Related URL: [description|http://jira.com]");
+  }
+
+  @Test
+  public void performAction() throws IOException, InvalidTransitionException {
+    jiraFacade = new JiraItsFacade(jiraClient);
+    jiraFacade.performAction(ISSUE_KEY, ACTION);
+    verify(jiraClient).doTransition(ISSUE_KEY, ACTION);
+  }
+
+  @Test
+  public void exists() throws IOException {
+    jiraFacade = new JiraItsFacade(jiraClient);
+    jiraFacade.exists(ISSUE_KEY);
+    verify(jiraClient).issueExists(ISSUE_KEY);
+  }
+}