From 2debfdc82c6734432f0c60bc96193ff5dde0a353 Mon Sep 17 00:00:00 2001 From: "Kipchumba C. Bett" Date: Fri, 8 Mar 2024 20:12:49 +0300 Subject: [PATCH] Add unit tests for resource operations --- .../camel/frappe/sdk/FrappeClientBuilder.java | 4 +- .../camel/frappe/sdk/api/FrappeResponse.java | 6 ++ .../sdk/internal/DefaultFrappeResponse.java | 5 ++ .../internal/operation/AbstractOperation.java | 4 +- .../operation/DefaultDeleteOperation.java | 2 + .../operation/DefaultPutOperation.java | 2 + ....java => DefaultFrappeAuthentication.java} | 6 +- .../security/cookie/InMemoryCookieJar.java | 6 +- .../operation/DefaultDeleteOperationTest.java | 67 +++++++++++++++ .../operation/DefaultPostOperationTest.java | 78 +++++++++++++++++ .../operation/DefaultPutOperationTest.java | 86 +++++++++++++++++++ ...a => DefaultFrappeAuthenticationTest.java} | 8 +- 12 files changed, 260 insertions(+), 14 deletions(-) rename camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/{FrappeBasicAuthentication.java => DefaultFrappeAuthentication.java} (92%) create mode 100644 camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperationTest.java create mode 100644 camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPostOperationTest.java create mode 100644 camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperationTest.java rename camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/{FrappeBasicAuthenticationTest.java => DefaultFrappeAuthenticationTest.java} (76%) diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/FrappeClientBuilder.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/FrappeClientBuilder.java index 7e7d9d1..dd159a8 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/FrappeClientBuilder.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/FrappeClientBuilder.java @@ -2,7 +2,7 @@ import com.ozonehis.camel.frappe.sdk.api.security.FrappeAuthentication; import com.ozonehis.camel.frappe.sdk.api.transformer.Transformer; -import com.ozonehis.camel.frappe.sdk.internal.security.FrappeBasicAuthentication; +import com.ozonehis.camel.frappe.sdk.internal.security.DefaultFrappeAuthentication; import com.ozonehis.camel.frappe.sdk.internal.transformer.JacksonTransformer; import java.util.concurrent.TimeUnit; @@ -37,7 +37,7 @@ public static FrappeClientBuilder newClient(String baseApiUrl, FrappeAuthenticat } public static FrappeClientBuilder newClient(String baseApiUrl, String username, String password) { - return new FrappeClientBuilder(baseApiUrl, new FrappeBasicAuthentication(username, password)); + return new FrappeClientBuilder(baseApiUrl, new DefaultFrappeAuthentication(username, password)); } public FrappeClientBuilder maxIdleConnections(int maxIdleConnections) { diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/api/FrappeResponse.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/api/FrappeResponse.java index b4d8427..22bf114 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/api/FrappeResponse.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/api/FrappeResponse.java @@ -44,6 +44,12 @@ public interface FrappeResponse extends Closeable { */ int code(); + /** + * This method returns the response message. + * @return The response message. + */ + String message(); + /** * This method returns the response body. * @return The response body. diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/DefaultFrappeResponse.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/DefaultFrappeResponse.java index 155dbd4..e336047 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/DefaultFrappeResponse.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/DefaultFrappeResponse.java @@ -43,6 +43,11 @@ public int code() { return response.code(); } + @Override + public String message() { + return response.message(); + } + @Override public ResponseBody responseBody() { return response.body(); diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/AbstractOperation.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/AbstractOperation.java index 32b86f8..b241809 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/AbstractOperation.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/AbstractOperation.java @@ -62,9 +62,7 @@ public ParameterizedOperation withParameters(Map parameters) @Override public ParameterizedOperation withParameter(String name, String value) { - List values = queryParams.computeIfAbsent(name, k -> new ArrayList<>()); - values.add(value); - this.queryParams.put(name, values); + this.queryParams.computeIfAbsent(name, k -> new ArrayList<>()).add(value); return this; } diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperation.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperation.java index 4c1a9ed..8a6eac2 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperation.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperation.java @@ -4,9 +4,11 @@ import com.ozonehis.camel.frappe.sdk.api.operation.DeleteOperation; import com.ozonehis.camel.frappe.sdk.api.transformer.Transformer; import com.ozonehis.camel.frappe.sdk.internal.DefaultFrappeResponse; +import lombok.Getter; import okhttp3.OkHttpClient; import okhttp3.Request; +@Getter public class DefaultDeleteOperation extends AbstractResourceOperation implements DeleteOperation { private String nameOfResourceToBeDeleted; diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperation.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperation.java index 5be6cd5..7fd1872 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperation.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperation.java @@ -4,10 +4,12 @@ import com.ozonehis.camel.frappe.sdk.api.operation.PutOperation; import com.ozonehis.camel.frappe.sdk.api.transformer.Transformer; import com.ozonehis.camel.frappe.sdk.internal.DefaultFrappeResponse; +import lombok.Getter; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; +@Getter public class DefaultPutOperation extends AbstractResourceOperation implements PutOperation { private String nameOfResourceToBeUpdated; diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/FrappeBasicAuthentication.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/DefaultFrappeAuthentication.java similarity index 92% rename from camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/FrappeBasicAuthentication.java rename to camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/DefaultFrappeAuthentication.java index 0b1bd08..688954f 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/FrappeBasicAuthentication.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/DefaultFrappeAuthentication.java @@ -12,13 +12,13 @@ import org.jetbrains.annotations.NotNull; @Slf4j -public class FrappeBasicAuthentication implements FrappeAuthentication { +public class DefaultFrappeAuthentication implements FrappeAuthentication { private final String username; private final String password; - public FrappeBasicAuthentication(String username, String password) { + public DefaultFrappeAuthentication(String username, String password) { this.username = username; this.password = password; } @@ -59,7 +59,7 @@ private Response executeRequest(Request request) throws IOException { private List extractCookies(Response response) { if (response.isSuccessful()) { - log.info("Logged in successfully"); + log.info("Authentication successful setting session cookie."); return response.headers("set-cookie"); } else { log.error("Failed to login, {}", response.body()); diff --git a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/cookie/InMemoryCookieJar.java b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/cookie/InMemoryCookieJar.java index cb6a66a..9dec04a 100644 --- a/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/cookie/InMemoryCookieJar.java +++ b/camel-frappe-api/src/main/java/com/ozonehis/camel/frappe/sdk/internal/security/cookie/InMemoryCookieJar.java @@ -21,8 +21,10 @@ public List loadForRequest(@NotNull HttpUrl httpUrl) { @Override public void saveFromResponse(@NotNull HttpUrl httpUrl, @NotNull List cookies) { - this.cookiesCache.removeAll(cookies.stream().map(WrappedCookie::new).toList()); - this.cookiesCache.addAll(cookies.stream().map(WrappedCookie::new).toList()); + List wrappedCookies = + cookies.stream().map(WrappedCookie::new).toList(); + this.cookiesCache.removeAll(wrappedCookies); + this.cookiesCache.addAll(wrappedCookies); } @Synchronized diff --git a/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperationTest.java b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperationTest.java new file mode 100644 index 0000000..45425c1 --- /dev/null +++ b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultDeleteOperationTest.java @@ -0,0 +1,67 @@ +package com.ozonehis.camel.frappe.sdk.internal.operation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.when; + +import com.ozonehis.camel.frappe.sdk.api.FrappeResponse; +import okhttp3.Request; +import okhttp3.Response; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; + +class DefaultDeleteOperationTest { + + @Mock + private okhttp3.OkHttpClient httpClient; + + @Mock + private okhttp3.Call call; + + private DefaultDeleteOperation defaultDeleteOperation; + + private static AutoCloseable mocksCloser; + + @BeforeEach + void setUp() { + mocksCloser = org.mockito.MockitoAnnotations.openMocks(this); + defaultDeleteOperation = new DefaultDeleteOperation("http://localhost", "doctype", httpClient, null); + } + + @AfterAll + static void closeMocks() throws Exception { + mocksCloser.close(); + } + + @Test + @DisplayName("doResourceExecute should return FrappeResponse when request is successful") + void doResourceExecuteShouldReturnFrappeResponseWhenRequestIsSuccessful() throws Exception { + byte[] resourceAsBytes = "test".getBytes(); + Request.Builder requestBuilder = new Request.Builder().url("http://localhost"); + + when(httpClient.newCall(Mockito.any(Request.class))).thenReturn(call); + Response.Builder responseBuilder = new Response.Builder(); + responseBuilder.code(200); + responseBuilder.message("Deleted"); + responseBuilder.request(new Request.Builder().url("http://localhost").build()); + responseBuilder.body(okhttp3.ResponseBody.create("{}", okhttp3.MediaType.parse("application/json"))); + responseBuilder.protocol(okhttp3.Protocol.HTTP_1_1); + when(call.execute()).thenReturn(responseBuilder.build()); + + FrappeResponse response = defaultDeleteOperation.doResourceExecute(resourceAsBytes, requestBuilder); + + assertEquals(200, response.code()); + assertEquals("Deleted", response.message()); + } + + @Test + @DisplayName("withName should set the name of the resource to be deleted") + void withNameShouldSetTheNameOfTheResourceToBeUpdated() { + String resourceName = "testResource"; + defaultDeleteOperation.withName(resourceName); + assertEquals(resourceName, defaultDeleteOperation.getNameOfResourceToBeDeleted()); + } +} diff --git a/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPostOperationTest.java b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPostOperationTest.java new file mode 100644 index 0000000..c3a9331 --- /dev/null +++ b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPostOperationTest.java @@ -0,0 +1,78 @@ +package com.ozonehis.camel.frappe.sdk.internal.operation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.ozonehis.camel.frappe.sdk.api.FrappeClientException; +import com.ozonehis.camel.frappe.sdk.api.FrappeResponse; +import java.io.IOException; +import okhttp3.Request; +import okhttp3.Response; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +class DefaultPostOperationTest { + + @Mock + private okhttp3.OkHttpClient httpClient; + + @Mock + private okhttp3.Call call; + + private DefaultPostOperation defaultPostOperation; + + private static AutoCloseable mocksCloser; + + @BeforeEach + void setUp() { + mocksCloser = org.mockito.MockitoAnnotations.openMocks(this); + defaultPostOperation = new DefaultPostOperation("http://localhost", "doctype", httpClient, null); + } + + @AfterAll + static void closeMocks() throws Exception { + mocksCloser.close(); + } + + @Test + @DisplayName("doResourceExecute should return FrappeResponse when request is successful") + void doResourceExecuteShouldReturnFrappeResponseWhenRequestIsSuccessful() throws IOException { + byte[] resourceAsBytes = "test".getBytes(); + Request.Builder requestBuilder = new Request.Builder().url("http://localhost"); + + when(httpClient.newCall(any(Request.class))).thenReturn(call); + Response.Builder responseBuilder = new Response.Builder(); + responseBuilder.code(200); + responseBuilder.message("OK"); + responseBuilder.request(new Request.Builder().url("http://localhost").build()); + responseBuilder.body(okhttp3.ResponseBody.create("{}", okhttp3.MediaType.parse("application/json"))); + responseBuilder.protocol(okhttp3.Protocol.HTTP_1_1); + when(call.execute()).thenReturn(responseBuilder.build()); + + FrappeResponse response = defaultPostOperation.doResourceExecute(resourceAsBytes, requestBuilder); + + assertNotNull(response); + assertEquals(200, response.code()); + assertEquals("OK", response.message()); + } + + @Test + @DisplayName("doResourceExecute should throw IOException when request fails") + void doResourceExecuteShouldThrowIOExceptionWhenRequestFails() throws IOException { + byte[] resourceAsBytes = "test".getBytes(); + Request.Builder requestBuilder = new Request.Builder().url("http://localhost"); + + when(httpClient.newCall(any(Request.class))).thenReturn(call); + when(call.execute()).thenThrow(IOException.class); + + assertThrows( + FrappeClientException.class, + () -> defaultPostOperation.doResourceExecute(resourceAsBytes, requestBuilder)); + } +} diff --git a/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperationTest.java b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperationTest.java new file mode 100644 index 0000000..4d092ad --- /dev/null +++ b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/operation/DefaultPutOperationTest.java @@ -0,0 +1,86 @@ +package com.ozonehis.camel.frappe.sdk.internal.operation; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +import com.ozonehis.camel.frappe.sdk.api.FrappeClientException; +import com.ozonehis.camel.frappe.sdk.api.FrappeResponse; +import java.io.IOException; +import okhttp3.Request; +import okhttp3.Response; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; + +class DefaultPutOperationTest { + + @Mock + private okhttp3.OkHttpClient httpClient; + + @Mock + private okhttp3.Call call; + + private DefaultPutOperation defaultPutOperation; + + private static AutoCloseable mocksCloser; + + @BeforeEach + void setUp() { + mocksCloser = org.mockito.MockitoAnnotations.openMocks(this); + defaultPutOperation = new DefaultPutOperation("http://localhost", "doctype", httpClient, null); + } + + @AfterAll + static void closeMocks() throws Exception { + mocksCloser.close(); + } + + @Test + @DisplayName("doResourceExecute should return FrappeResponse when request is successful") + void doResourceExecuteShouldReturnFrappeResponseWhenRequestIsSuccessful() throws IOException { + byte[] resourceAsBytes = "test".getBytes(); + Request.Builder requestBuilder = new Request.Builder().url("http://localhost"); + + when(httpClient.newCall(any(Request.class))).thenReturn(call); + Response.Builder responseBuilder = new Response.Builder(); + responseBuilder.code(204); + responseBuilder.message("Updated"); + responseBuilder.request(new Request.Builder().url("http://localhost").build()); + responseBuilder.body(okhttp3.ResponseBody.create("{}", okhttp3.MediaType.parse("application/json"))); + responseBuilder.protocol(okhttp3.Protocol.HTTP_1_1); + when(call.execute()).thenReturn(responseBuilder.build()); + + FrappeResponse response = defaultPutOperation.doResourceExecute(resourceAsBytes, requestBuilder); + + assertNotNull(response); + assertEquals(204, response.code()); + assertEquals("Updated", response.message()); + } + + @Test + @DisplayName("doResourceExecute should throw IOException when request fails") + void doResourceExecuteShouldThrowIOExceptionWhenRequestFails() throws IOException { + byte[] resourceAsBytes = "test".getBytes(); + Request.Builder requestBuilder = new Request.Builder().url("http://localhost"); + + when(httpClient.newCall(any(Request.class))).thenReturn(call); + when(call.execute()).thenThrow(IOException.class); + + assertThrows( + FrappeClientException.class, + () -> defaultPutOperation.doResourceExecute(resourceAsBytes, requestBuilder)); + } + + @Test + @DisplayName("withName should set the name of the resource to be updated") + void withNameShouldSetTheNameOfTheResourceToBeUpdated() { + String resourceName = "testResource"; + defaultPutOperation.withName(resourceName); + assertEquals(resourceName, defaultPutOperation.getNameOfResourceToBeUpdated()); + } +} diff --git a/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/FrappeBasicAuthenticationTest.java b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/DefaultFrappeAuthenticationTest.java similarity index 76% rename from camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/FrappeBasicAuthenticationTest.java rename to camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/DefaultFrappeAuthenticationTest.java index 9b0e76a..53fd658 100644 --- a/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/FrappeBasicAuthenticationTest.java +++ b/camel-frappe-api/src/test/java/com/ozonehis/camel/frappe/sdk/internal/security/DefaultFrappeAuthenticationTest.java @@ -12,12 +12,12 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; -class FrappeBasicAuthenticationTest { +class DefaultFrappeAuthenticationTest { @Mock private Request request; - private FrappeBasicAuthentication frappeBasicAuthentication; + private DefaultFrappeAuthentication defaultFrappeAuthentication; private static AutoCloseable mocksCloser; @@ -25,7 +25,7 @@ class FrappeBasicAuthenticationTest { void setUp() { mocksCloser = openMocks(this); when(request.url()).thenReturn(HttpUrl.get("http://localhost:8080")); - frappeBasicAuthentication = new FrappeBasicAuthentication("username", "password"); + defaultFrappeAuthentication = new DefaultFrappeAuthentication("username", "password"); } @AfterAll @@ -37,6 +37,6 @@ static void closeMocks() throws Exception { @DisplayName("getBaseUrl should return correct base url") void getBaseUrlShouldReturnCorrectBaseUrl() { when(request.url()).thenReturn(HttpUrl.get("http://localhost:8080")); - assertEquals("http://localhost:8080", frappeBasicAuthentication.getBaseUrl(request)); + assertEquals("http://localhost:8080", defaultFrappeAuthentication.getBaseUrl(request)); } }