From b9d4ae2a8e06388ea34df48016bdfca2a7fea622 Mon Sep 17 00:00:00 2001 From: "agrja.rastogi" Date: Wed, 4 Feb 2026 13:47:24 +0530 Subject: [PATCH 1/2] Add api_test.mustache template for auto-generated test classes This template generates comprehensive unit tests for all API operations. Each test: - Loads prerequisite data created by Terraform - Extracts method parameters from the prerequisite data - Executes the actual API method - Validates HTTP response codes (200, 201, 202, 204) The template includes: - Smart parameter extraction that handles field name variations - Support for file uploads via file_path parameter - Automatic model deserialization with fallback to alternative class names - Comprehensive error handling and validation - Javadoc comments explaining test behavior This enables automated testing of all Okta SDK operations against live APIs while maintaining code consistency and reducing manual test maintenance. --- .../custom_templates/api_test.mustache | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 api/src/main/resources/custom_templates/api_test.mustache diff --git a/api/src/main/resources/custom_templates/api_test.mustache b/api/src/main/resources/custom_templates/api_test.mustache new file mode 100644 index 00000000000..643ff1eca61 --- /dev/null +++ b/api/src/main/resources/custom_templates/api_test.mustache @@ -0,0 +1,154 @@ +package {{package}}; + +import {{invokerPackage}}.ApiException; +import {{modelPackage}}.*; +import com.okta.sdk.helper.PresetHelper; +import com.okta.sdk.helper.TerraformHelper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.DisplayName; + +{{#imports}} +import {{import}}; +{{/imports}} + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +/** + * Auto-generated unit tests for {{classname}} operations + * + * NOTE: This test class requires Terraform-generated prerequisite data to run. + * Tests will fail if the TF_OUTPUTS environment variable is not set with the + * required test prerequisite data. + */ +public class {{classname}}Test { + + private {{classname}} apiClient; + private PresetHelper presetHelper; + private TerraformHelper terraformHelper; + + @BeforeEach + public void setUp() { + presetHelper = new PresetHelper(); + terraformHelper = new TerraformHelper(); + apiClient = new {{classname}}(presetHelper.getApiClient()); + } + +{{#operations}} +{{#operation}} + /** + * Test case for {{operationId}} operation. + * + * This test executes the actual API method with parameters extracted from + * prerequisite data created by Terraform. It validates HTTP response codes. + * + * Method name: test_{{operationId}} + */ + @Test + @DisplayName("Test {{operationId}} operation") + @SuppressWarnings("unchecked") + public void test_{{operationId}}() throws Exception { + // Load prerequisite data from Terraform + Map prerequisiteData = terraformHelper.getPrerequisiteDataForTest("test_{{operationId}}"); + + // Fail if no prerequisite data found - tests require Terraform data + if (prerequisiteData.isEmpty()) { + throw new AssertionError("No prerequisite data found in Terraform output for test: test_{{operationId}}"); + } + + // Extract parameters from prerequisite data + Map payload = (Map) prerequisiteData.getOrDefault("payload", new HashMap<>()); + Map prerequisiteObject = (Map) prerequisiteData.getOrDefault("prerequisite_object", new HashMap<>()); + + // Handle file uploads if present + byte[] fileContent = null; + if (payload.containsKey("file_path")) { + String filePath = payload.get("file_path").toString(); + fileContent = Files.readAllBytes(Paths.get(filePath)); + } + + // Execute the API method with parameters extracted from prerequisiteData + try { + {{#returnType}} + {{{returnType}}} response = apiClient.{{operationId}}( + {{#allParams}} + {{#isBodyParam}}extractParameterWithType(prerequisiteData, "{{paramName}}", null, "{{datatype}}"){{/isBodyParam}}{{^isBodyParam}}extractParameter(prerequisiteData, "{{paramName}}", null){{/isBodyParam}}{{^-last}}, {{/-last}} + {{/allParams}} + ); + + // Verify response is not null + if (response == null) { + throw new AssertionError("Response should not be null for {{operationId}}"); + } + {{/returnType}} + {{^returnType}} + apiClient.{{operationId}}( + {{#allParams}} + {{#isBodyParam}}extractParameterWithType(prerequisiteData, "{{paramName}}", null, "{{datatype}}"){{/isBodyParam}}{{^isBodyParam}}extractParameter(prerequisiteData, "{{paramName}}", null){{/isBodyParam}}{{^-last}}, {{/-last}} + {{/allParams}} + ); + {{/returnType}} + } catch (ApiException e) { + // Verify the HTTP response status code is valid (200, 201, 202, 204) + int code = e.getCode(); + if (!(code == 200 || code == 201 || code == 202 || code == 204)) { + throw new AssertionError("API returned unexpected status code: " + code); + } + } + } + +{{/operation}} +{{/operations}} + + /** + * Helper method to extract a parameter from prerequisite data. + * Delegates to TerraformHelper.extractParameter for smart field name resolution. + * + * @param prerequisiteData Map containing Terraform prerequisite data + * @param paramName Name of the parameter to extract + * @param defaultValue Default value if parameter is not found + * @return The extracted parameter value or default value + */ + @SuppressWarnings("unchecked") + private T extractParameter(Map prerequisiteData, String paramName, T defaultValue) { + Object value = TerraformHelper.extractParameter(prerequisiteData, paramName, defaultValue); + return (T) value; + } + + /** + * Helper method to extract a parameter with a specific target class for deserialization. + * This is useful when a parameter can be multiple model types (e.g., Group vs AddGroupRequest). + * + * @param prerequisiteData Map containing Terraform prerequisite data + * @param paramName Name of the parameter to extract + * @param defaultValue Default value if parameter is not found + * @param targetClassName Fully qualified class name for deserialization + * @return The extracted parameter value deserialized to the target class, or default value + */ + @SuppressWarnings("unchecked") + private T extractParameterWithType(Map prerequisiteData, String paramName, T defaultValue, String targetClassName) { + Object value = TerraformHelper.extractParameter(prerequisiteData, paramName, defaultValue, targetClassName); + return (T) value; + } + + /** + * Convert camelCase to snake_case + */ + private String toSnakeCase(String camelCase) { + if (camelCase == null || camelCase.isEmpty()) return camelCase; + StringBuilder result = new StringBuilder(); + for (int i = 0; i < camelCase.length(); i++) { + char c = camelCase.charAt(i); + if (Character.isUpperCase(c)) { + if (i > 0) result.append("_"); + result.append(Character.toLowerCase(c)); + } else { + result.append(c); + } + } + return result.toString(); + } +} From c80575a15c32a9b5e44027220bca23f39967345b Mon Sep 17 00:00:00 2001 From: "agrja.rastogi" Date: Wed, 4 Feb 2026 14:14:40 +0530 Subject: [PATCH 2/2] Remove unused toSnakeCase method from api_test.mustache The toSnakeCase method was not being called anywhere in the template. The camelCase to snake_case conversion is already handled by TerraformHelper.getPrerequisiteDataForTest() on the backend. --- .../custom_templates/api_test.mustache | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/api/src/main/resources/custom_templates/api_test.mustache b/api/src/main/resources/custom_templates/api_test.mustache index 643ff1eca61..a3e69d1ba6b 100644 --- a/api/src/main/resources/custom_templates/api_test.mustache +++ b/api/src/main/resources/custom_templates/api_test.mustache @@ -133,22 +133,4 @@ public class {{classname}}Test { Object value = TerraformHelper.extractParameter(prerequisiteData, paramName, defaultValue, targetClassName); return (T) value; } - - /** - * Convert camelCase to snake_case - */ - private String toSnakeCase(String camelCase) { - if (camelCase == null || camelCase.isEmpty()) return camelCase; - StringBuilder result = new StringBuilder(); - for (int i = 0; i < camelCase.length(); i++) { - char c = camelCase.charAt(i); - if (Character.isUpperCase(c)) { - if (i > 0) result.append("_"); - result.append(Character.toLowerCase(c)); - } else { - result.append(c); - } - } - return result.toString(); - } }