Add tests
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PatchSetReviewerTests.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PatchSetReviewerTests.java
new file mode 100644
index 0000000..4d7b7ab
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/PatchSetReviewerTests.java
@@ -0,0 +1,121 @@
+package com.googlesource.gerrit.plugins.chatgpt;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.github.tomakehurst.wiremock.verification.LoggedRequest;
+import com.google.common.net.HttpHeaders;
+import com.googlesource.gerrit.plugins.chatgpt.client.GerritClient;
+import com.googlesource.gerrit.plugins.chatgpt.client.OpenAiClient;
+import com.googlesource.gerrit.plugins.chatgpt.client.UriResourceLocator;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.entity.ContentType;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Base64;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+@Slf4j
+@RunWith(MockitoJUnitRunner.class)
+public class PatchSetReviewerTests {
+
+    private static final String CHANGE_ID = "myChangeId";
+
+    @Rule
+    public WireMockRule wireMockRule = new WireMockRule(9527);
+
+    private Configuration configuration;
+
+    private GerritClient gerritClient;
+
+    private OpenAiClient openAiClient;
+
+    private PatchSetReviewer patchSetReviewer;
+
+    private PatchSetCreated patchSetCreated;
+
+    @Before
+    public void before() {
+        initializePatchSetReviewer();
+        setupMockRequests();
+    }
+
+    private void initializePatchSetReviewer() {
+        configuration = Mockito.mock(Configuration.class);
+        when(configuration.getGerritAuthBaseUrl()).thenReturn("http://localhost:9527");
+        when(configuration.getGptDomain()).thenReturn("http://localhost:9527");
+        when(configuration.getMaxReviewLines()).thenReturn(500);
+
+        gerritClient = Mockito.spy(new GerritClient() {
+            @Override
+            public Configuration getConfiguration() {
+                return configuration;
+            }
+        });
+
+        openAiClient = Mockito.spy(new OpenAiClient() {
+            @Override
+            public Configuration getConfiguration() {
+                return configuration;
+            }
+        });
+
+        patchSetReviewer = new PatchSetReviewer(configuration, gerritClient, openAiClient);
+        patchSetCreated = new PatchSetCreated(patchSetReviewer);
+    }
+
+    private void setupMockRequests() {
+        // Mocks the behavior of the getPatchSet request
+        stubFor(get(urlEqualTo(URI.create(configuration.getGerritAuthBaseUrl() +
+                UriResourceLocator.gerritPatchSetUri(CHANGE_ID)).getPath()))
+                .willReturn(aResponse()
+                        .withStatus(HTTP_OK)
+                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
+                        .withBody(Base64.getEncoder().encodeToString("myPatch".getBytes()))));
+
+        // Mocks the behavior of the askGpt request
+        byte[] gptAnswer = Base64.getDecoder().decode("ZGF0YTogeyJpZCI6ImNoYXRjbXBsLTdSZDVOYVpEOGJNVTRkdnBVV2" +
+                "9hM3Q2RG83RkkzIiwib2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIiwiY3JlYXRlZCI6MTY4NjgxOTQ1NywibW9kZWw" +
+                "iOiJncHQtMy41LXR1cmJvLTAzMDEiLCJjaG9pY2VzIjpbeyJkZWx0YSI6eyJyb2xlIjoiYXNzaXN0YW50In0sImluZGV4Ijow" +
+                "LCJmaW5pc2hfcmVhc29uIjpudWxsfV19CgpkYXRhOiB7ImlkIjoiY2hhdGNtcGwtN1JkNU5hWkQ4Yk1VNGR2cFVXb2EzdDZEb" +
+                "zdGSTMiLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24uY2h1bmsiLCJjcmVhdGVkIjoxNjg2ODE5NDU3LCJtb2RlbCI6ImdwdC0" +
+                "zLjUtdHVyYm8tMDMwMSIsImNob2ljZXMiOlt7ImRlbHRhIjp7ImNvbnRlbnQiOiJIZWxsbyJ9LCJpbmRleCI6MCwiZmluaXNo" +
+                "X3JlYXNvbiI6bnVsbH1dfQoKZGF0YTogeyJpZCI6ImNoYXRjbXBsLTdSZDVOYVpEOGJNVTRkdnBVV29hM3Q2RG83RkkzIiwib" +
+                "2JqZWN0IjoiY2hhdC5jb21wbGV0aW9uLmNodW5rIiwiY3JlYXRlZCI6MTY4NjgxOTQ1NywibW9kZWwiOiJncHQtMy41LXR1cm" +
+                "JvLTAzMDEiLCJjaG9pY2VzIjpbeyJkZWx0YSI6eyJjb250ZW50IjoiISJ9LCJpbmRleCI6MCwiZmluaXNoX3JlYXNvbiI" +
+                "6bnVsbH1dfQ==");
+        stubFor(post(urlEqualTo(URI.create(configuration.getGptDomain()
+                + UriResourceLocator.chatCompletionsUri()).getPath()))
+                .willReturn(aResponse()
+                        .withStatus(HTTP_OK)
+                        .withHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString())
+                        .withBody(new String(gptAnswer))));
+
+        // Mocks the behavior of the postReview request
+        stubFor(post(urlEqualTo(URI.create(configuration.getGerritAuthBaseUrl()
+                + UriResourceLocator.gerritCommentUri(CHANGE_ID)).getPath()))
+                .willReturn(aResponse()
+                        .withStatus(HTTP_OK)));
+    }
+
+    @Test
+    public void review() throws IOException, InterruptedException {
+        patchSetReviewer.review(CHANGE_ID);
+
+        LoggedRequest firstMatchingRequest = findAll(postRequestedFor(urlEqualTo(UriResourceLocator
+                .gerritPatchSetUri(CHANGE_ID)))).get(0);
+        String requestBody = firstMatchingRequest.getBodyAsString();
+        assertEquals("{\"message\":\"Hello!\\n\"}", requestBody);
+
+    }
+
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/chatgpt/integration/CodeReviewPluginIT.java b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/integration/CodeReviewPluginIT.java
new file mode 100644
index 0000000..f352326
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/chatgpt/integration/CodeReviewPluginIT.java
@@ -0,0 +1,61 @@
+package com.googlesource.gerrit.plugins.chatgpt.integration;
+
+import com.googlesource.gerrit.plugins.chatgpt.Configuration;
+import com.googlesource.gerrit.plugins.chatgpt.client.GerritClient;
+import com.googlesource.gerrit.plugins.chatgpt.client.OpenAiClient;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.IOException;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+
+//@Ignore("This test suite is designed for integration testing and is not intended to be executed during the regular build process")
+@Slf4j
+@RunWith(MockitoJUnitRunner.class)
+public class CodeReviewPluginIT {
+    @Mock
+    private Configuration configuration;
+
+    @InjectMocks
+    private GerritClient gerritClient;
+
+    @InjectMocks
+    private OpenAiClient openAiClient;
+
+    @Test
+    public void sayHelloToGPT() throws IOException, InterruptedException {
+        when(configuration.getGptToken()).thenReturn("Your GPT token");
+        when(configuration.getGptModel()).thenReturn(Configuration.DEFAULT_GPT_MODEL);
+        when(configuration.getGptPrompt()).thenReturn(Configuration.DEFAULT_GPT_PROMPT);
+
+        String answer = openAiClient.ask("hello");
+        log.info("answer: {}", answer);
+        assertNotNull(answer);
+    }
+
+    @Test
+    public void getPatchSet() throws IOException, InterruptedException {
+        when(configuration.getGerritAuthBaseUrl()).thenReturn("Your Gerrit URL");
+        when(configuration.getGerritUserName()).thenReturn("Your Gerrit username");
+        when(configuration.getGerritPassword()).thenReturn("Your Gerrit password");
+
+        String patchSet = gerritClient.getPatchSet("${changeId}");
+        log.info("patchSet: {}", patchSet);
+        assertNotNull(patchSet);
+    }
+
+    @Test
+    public void postComment() throws IOException, InterruptedException {
+        when(configuration.getGerritAuthBaseUrl()).thenReturn("Your Gerrit URL");
+        when(configuration.getGerritUserName()).thenReturn("Your Gerrit username");
+        when(configuration.getGerritPassword()).thenReturn("Your Gerrit password");
+
+        gerritClient.postComment("Your changeId", "message");
+    }
+}
diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml
new file mode 100644
index 0000000..4b12a6d
--- /dev/null
+++ b/src/test/resources/logback.xml
@@ -0,0 +1,11 @@
+<configuration>
+    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder>
+            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+        </encoder>
+    </appender>
+
+    <root level="debug">
+        <appender-ref ref="STDOUT"/>
+    </root>
+</configuration>
\ No newline at end of file