Skip to content

Commit

Permalink
http client unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
WaciX committed Sep 9, 2023
1 parent e005e47 commit 2f61718
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,30 @@
package com.bitwarden.passwordless;

import com.bitwarden.passwordless.factory.DataFactory;
import com.bitwarden.passwordless.model.TestRequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.*;

class PasswordlessHttpClientTest {
Expand All @@ -19,41 +37,91 @@ class PasswordlessHttpClientTest {
.failOnUnmatchedRequests(true)
.build();

PasswordlessOptions passwordlessOptions;
PasswordlessHttpClient passwordlessHttpClient;

@BeforeEach
void setUp() {
passwordlessOptions = DataFactory.passwordlessOptions(wireMock.baseUrl());
passwordlessHttpClient = PasswordlessClientBuilder.create(passwordlessOptions)
.buildPasswordlessHttpClient();
}

@AfterEach
void tearDown() {
void tearDown() throws IOException {
if (passwordlessHttpClient != null) {
passwordlessHttpClient.close();
passwordlessHttpClient = null;
}
}

@Test
void createPostRequest_invalidApiUrl_IOException() {
void createPostRequest_invalidApiUrl_IOException() throws IOException {
passwordlessHttpClient.close();

PasswordlessOptions passwordlessOptions = DataFactory.passwordlessOptions("http://localhost^:8080");
passwordlessHttpClient = PasswordlessClientBuilder.create(passwordlessOptions)
.buildPasswordlessHttpClient();

TestRequest testRequest = DataFactory.testRequest();

assertThatThrownBy(() -> passwordlessHttpClient.createPostRequest("login", testRequest))
.isInstanceOf(IOException.class)
.hasMessageContaining("http://localhost^:8080");
}

@Test
void createPostRequest_nullPayload_NPE() {
assertThatThrownBy(() -> passwordlessHttpClient.createPostRequest("login", null))
.isInstanceOf(NullPointerException.class)
.hasMessage("POST payload is null");
}

@Test
void createPostRequest_payload_noError() {
void createPostRequest_payload_noError() throws IOException, ProtocolException, URISyntaxException {
TestRequest testRequest = DataFactory.testRequest();
String testRequestJson = passwordlessHttpClient.objectMapper.writeValueAsString(testRequest);

ClassicHttpRequest request = passwordlessHttpClient.createPostRequest("login", testRequest);
validateRequest(request, "POST", "/login", testRequestJson);
}

@Test
void createGetRequest_invalidApiUrl_IOException() {
void createGetRequest_invalidApiUrl_IOException() throws IOException {
passwordlessHttpClient.close();

PasswordlessOptions passwordlessOptions = DataFactory.passwordlessOptions("http://localhost^:8080");
passwordlessHttpClient = PasswordlessClientBuilder.create(passwordlessOptions)
.buildPasswordlessHttpClient();

assertThatThrownBy(() -> passwordlessHttpClient.createGetRequest("login", Collections.singletonMap("userId", "testUser")))
.isInstanceOf(IOException.class)
.hasMessageContaining("http://localhost^:8080");
}

@Test
void createGetRequest_queryParametersNull_noError() {
void createGetRequest_queryParametersNull_noError() throws IOException, ProtocolException, URISyntaxException {
ClassicHttpRequest request = passwordlessHttpClient.createGetRequest("login", null);

validateRequest(request, "GET", "/login", null);
}

@Test
void createGetRequest_queryParametersEmpty_noError() {
void createGetRequest_queryParametersEmpty_noError() throws IOException, ProtocolException, URISyntaxException {
ClassicHttpRequest request = passwordlessHttpClient.createGetRequest("login", Collections.emptyMap());

validateRequest(request, "GET", "/login", null);
}

@Test
void createGetRequest_twoQueryParameters_noError() {
void createGetRequest_twoQueryParameters_noError() throws IOException, ProtocolException, URISyntaxException {
Map<String, String> queryParameters = new TreeMap<>();
queryParameters.put("page", "1");
queryParameters.put("userId", "testUser");

ClassicHttpRequest request = passwordlessHttpClient.createGetRequest("login", queryParameters);

validateRequest(request, "GET", "/login?page=1&userId=testUser", null);
}

@Test
Expand Down Expand Up @@ -91,4 +159,22 @@ void close_userProvidedHttpClient_httpClientNotClosed() {
@Test
void close_defaultHttpClient_httpClientClosed() {
}

private void validateRequest(ClassicHttpRequest request, String method, String path, String payloadJson)
throws IOException, ProtocolException, URISyntaxException {
assertThat(request).isNotNull();
assertThat(request.getMethod()).isEqualTo(method);
assertThat(request.getPath()).isEqualTo(path);
assertThat(request.getUri()).isEqualTo(URI.create(passwordlessOptions.getApiUrl() + path));
assertThat(request.getHeaders()).hasSize(1);
assertThat(request.getHeader("ApiSecret")).isNotNull()
.extracting(Header::getValue)
.isEqualTo(passwordlessOptions.getApiPrivateKey());
if (payloadJson != null) {
assertThat(request.getEntity()).isNotNull();
assertThat(EntityUtils.toString(request.getEntity())).isEqualTo(payloadJson);
} else {
assertThat(request.getEntity()).isNull();
}
}
}
22 changes: 22 additions & 0 deletions src/test/java/com/bitwarden/passwordless/factory/DataFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.bitwarden.passwordless.factory;

import com.bitwarden.passwordless.PasswordlessOptions;
import com.bitwarden.passwordless.model.TestRequest;
import lombok.experimental.UtilityClass;

@UtilityClass
public class DataFactory {
public PasswordlessOptions passwordlessOptions(String url) {
return PasswordlessOptions.builder()
.apiUrl(url)
.apiPrivateKey("javaapp:secret:34286d0b2cb24b8687d1639d20eb29fa")
.build();
}

public TestRequest testRequest() {
return TestRequest.builder()
.fieldNumber(123)
.build();
}

}
49 changes: 49 additions & 0 deletions src/test/java/com/bitwarden/passwordless/model/TestRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.bitwarden.passwordless.model;

import lombok.*;

import java.time.Instant;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

@Data
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
@Builder
public class TestRequest {
@NonNull
Integer fieldNumber;
@Builder.Default
Integer fieldNumberDefault = 123;

String fieldString;
@Builder.Default
String fieldStringDefault = "testString";

List<String> fieldList;
@Builder.Default
List<String> fieldListDefault = Arrays.asList("testString1", "testString2");

Boolean fieldBool;
@Builder.Default
Boolean fieldBoolDefault = true;

Instant fieldInstant;
@Builder.Default
Instant fieldInstantDefault = Instant.parse("2023-09-10T10:23:45.678910Z");

LocalDateTime fieldLocalDateTime;
@Builder.Default
LocalDateTime fieldLocalDateTimeDefault = LocalDateTime.parse("2022-11-23T20:08:35");

TestRequestInner testRequestInner;

@Data
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
@Builder
public static class TestRequestInner {
String fieldStringInner;
}
}
15 changes: 15 additions & 0 deletions src/test/java/com/bitwarden/passwordless/model/TestResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.bitwarden.passwordless.model;

import lombok.*;

import java.time.Instant;
import java.util.List;

@Data
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
@Builder
public class TestResponse {
Integer field1;
Instant field4;
}

0 comments on commit 2f61718

Please sign in to comment.