Skip to content

Commit f4683aa

Browse files
Made the description a bit brief and removed extra details
1 parent 28e4194 commit f4683aa

1 file changed

Lines changed: 2 additions & 192 deletions

File tree

README.md

Lines changed: 2 additions & 192 deletions
Original file line numberDiff line numberDiff line change
@@ -806,205 +806,15 @@ ApiClient client = Clients.builder()
806806

807807
## WireMock Integration Testing
808808

809-
### Overview
810-
811-
WireMock enables testing with the Okta Java SDK by providing a mock HTTP server that simulates Okta's API endpoints over HTTPS. This eliminates the need to hit actual Okta servers during development and testing, removing rate limit concerns and enabling rapid iteration.
812-
813-
### Problem
814-
815-
The Okta SDK requires HTTPS connections, and when using WireMock with self-signed certificates, the SDK's HTTP client must be configured to trust the mock server's certificate. This section demonstrates the complete setup.
816-
817-
### Solution Architecture
818-
819-
The solution consists of three components:
820-
821-
1. **Self-Signed Certificate Generation**: Automatically generates a JKS keystore with a self-signed certificate
822-
2. **WireMock HTTPS Configuration**: Configures WireMock server to use the certificate
823-
3. **Custom SSL Context**: Configures the Okta SDK's HTTP client to trust the certificate
824-
825-
### Implementation
826-
827-
#### Step 1: Automatic Certificate Generation
828-
829-
The test setup automatically generates a self-signed certificate on first run:
830-
831-
```java
832-
String keystorePath = Paths.get(KEYSTORE_PATH).toAbsolutePath().toString();
833-
java.io.File keystoreFile = new java.io.File(keystorePath);
834-
if (!keystoreFile.exists()) {
835-
ProcessBuilder pb = new ProcessBuilder(
836-
"keytool", "-genkey", "-alias", "wiremock", "-keyalg", "RSA",
837-
"-keystore", keystorePath,
838-
"-storepass", "password", "-keypass", "password",
839-
"-dname", "CN=localhost", "-validity", "365", "-noprompt"
840-
);
841-
int exitCode = pb.start().waitFor();
842-
if (exitCode != 0) {
843-
throw new RuntimeException("Failed to generate WireMock keystore");
844-
}
845-
}
846-
```
847-
848-
The certificate is generated once and reused for subsequent test runs. The `.gitignore` file excludes the keystore from version control to maintain security best practices.
849-
850-
#### Step 2: Configure WireMock Server
851-
852-
Start WireMock on HTTPS port 8443 using the generated certificate:
853-
854-
```java
855-
wireMockServer = new WireMockServer(
856-
WireMockConfiguration.wireMockConfig()
857-
.httpsPort(8443)
858-
.keystorePath(keystorePath)
859-
.keystorePassword("password")
860-
);
861-
wireMockServer.start();
862-
```
863-
864-
#### Step 3: Create Custom SSL Context
865-
866-
Load the keystore and configure an SSL context that trusts the self-signed certificate:
867-
868-
```java
869-
KeyStore trustStore = KeyStore.getInstance("JKS");
870-
try (FileInputStream fis = new FileInputStream(keystorePath)) {
871-
trustStore.load(fis, "password".toCharArray());
872-
}
873-
874-
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
875-
TrustManagerFactory.getDefaultAlgorithm());
876-
tmf.init(trustStore);
877-
878-
SSLContext sslContext = SSLContext.getInstance("TLS");
879-
sslContext.init(null, tmf.getTrustManagers(), new java.security.SecureRandom());
880-
```
881-
882-
#### Step 4: Configure HTTP Client with Custom SSL Context
883-
884-
Create the HTTP client with dynamic port allocation for thread safety:
885-
886-
```java
887-
// Find an available port for thread-safe parallel execution
888-
ServerSocket socket = new ServerSocket(0);
889-
int wiremockPort = socket.getLocalPort();
890-
socket.close();
891-
892-
org.apache.hc.client5.http.impl.classic.CloseableHttpClient httpClient =
893-
HttpClients.custom()
894-
.setConnectionManager(
895-
PoolingHttpClientConnectionManagerBuilder.create()
896-
.setSSLSocketFactory(
897-
new org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory(sslContext)
898-
)
899-
.build()
900-
)
901-
.build();
902-
```
903-
904-
#### Step 5: Create Okta API Client
905-
906-
Instantiate the API client with the custom HTTP client:
907-
908-
```java
909-
client = new ApiClient(httpClient, new com.okta.sdk.impl.cache.DisabledCacheManager());
910-
client.setBasePath("https://localhost:" + wiremockPort);
911-
912-
userApi = new UserApi(client);
913-
```
914-
915-
### Usage Example
916-
917-
Define API endpoint mocks using WireMock's stubFor pattern:
918-
919-
```java
920-
@Test
921-
public void testGetUser() throws ApiException {
922-
String userId = "00ub0oNGTSWTBKOLGLHN";
923-
924-
stubFor(get(urlEqualTo("/api/v1/users/" + userId))
925-
.willReturn(aResponse()
926-
.withStatus(200)
927-
.withHeader("Content-Type", "application/json")
928-
.withBody("{" +
929-
"\"id\":\"" + userId + "\"," +
930-
"\"status\":\"ACTIVE\"," +
931-
"\"profile\":{" +
932-
"\"email\":\"user@example.com\"" +
933-
"}" +
934-
"}")
935-
));
936-
937-
User user = userApi.getUser(userId, null, null);
938-
939-
assertNotNull(user);
940-
assertEquals(userId, user.getId());
941-
assertEquals("ACTIVE", user.getStatus().toString());
942-
}
943-
```
944-
945-
### Thread Safety
946-
947-
The implementation uses dynamic port allocation to ensure thread-safe parallel test execution:
948-
949-
```java
950-
ServerSocket socket = new ServerSocket(0); // OS assigns available port
951-
int wiremockPort = socket.getLocalPort();
952-
socket.close();
953-
```
954-
955-
This approach allows multiple test instances to run simultaneously, each with its own isolated WireMock server instance on a unique port.
956-
957-
### Reference Implementation
958-
959-
A complete working example is provided in `integration-tests/src/test/java/com/okta/sdk/tests/WireMockOktaClientTest.java` with test cases for:
960-
961-
- Single user retrieval (testGetUser)
962-
- User list operations (testListUsers)
963-
- HTTPS configuration verification (testWireMockHttps)
809+
WireMock can be configured to serve HTTPS with a self-signed certificate and custom KeyStore. The SDK's HTTP client can be configured with a custom SSLContext and TrustManager to accept the certificate. This implementation demonstrates both: automatic self-signed certificate generation, WireMock HTTPS configuration, and SDK HTTP client setup with a custom TrustManager. It also uses dynamic port allocation for thread-safe parallel test execution.
964810

965811
### Running the Tests
966812

967-
Execute the integration tests with:
968-
969813
```bash
970814
mvn test -Dtest=WireMockOktaClientTest -pl integration-tests
971815
```
972816

973-
Expected output:
974-
975-
```
976-
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
977-
```
978-
979-
### Prerequisites
980-
981-
- Java Development Kit (JDK) 8 or later
982-
- Apache Maven 3.6 or later
983-
- keytool (included with JDK)
984-
985-
### Troubleshooting
986-
987-
**Port Already in Use**
988-
989-
If port 8443 is in use, the dynamic port allocation in the current implementation automatically selects an available port. Ensure you pass the dynamically assigned port to the client configuration.
990-
991-
**Certificate Trust Issues**
992-
993-
Verify that the keystore file is generated and accessible:
994-
995-
```bash
996-
ls -la wiremock-keystore.jks
997-
```
998-
999-
If the file is missing or corrupted, delete it and run tests again to regenerate.
1000-
1001-
**keytool Not Found**
1002-
1003-
keytool is included with the JDK. Ensure JAVA_HOME is properly configured:
1004-
1005-
```bash
1006-
echo $JAVA_HOME
1007-
```
817+
See the complete implementation in `integration-tests/src/test/java/com/okta/sdk/tests/WireMockOktaClientTest.java`.
1008818

1009819
## Building the SDK
1010820

0 commit comments

Comments
 (0)