/
gns34
/
json-schema-faker-java
Обзор
Документация
Войти
/
gns34
/
json-schema-faker-java
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/test/java/com/github/jsonschemafaker/JsonSchemaFakerComprehensiveTest.java
1 031 строка
37 KB
ankit-d-sharma
Added json-schema-faker-java
01 авг 2025, 22:51
01 авг 2025, 22:51
8ff4abd
Код
Авторство
О чём код?
package com.github.jsonschemafaker; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.node.TextNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.github.jsonschemafaker.options.Options; import com.github.javafaker.Faker; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.util.Locale; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicBoolean; import static org.junit.jupiter.api.Assertions.*; /** * Comprehensive test suite covering all features of JsonSchemaFaker. * Tests include multithreaded scenarios, custom generators, advanced JSON Schema features, and edge cases. */ public class JsonSchemaFakerComprehensiveTest { private JsonSchemaFaker faker; private Options options; @BeforeEach public void setUp() { options = Options.builder() .locale(Locale.ENGLISH) .maxArrayLength(1000) .minArrayLength(1) .maxStringLength(100) .minStringLength(1) .useDefaultValues(true) .generateOptionalProperties(true) .useExamples(true) .useEnumValues(true) .generateNullValues(false) .nullProbability(0.1) .uniqueItems(false) .usePatterns(true) .useFormats(true) .useMinimum(true) .useMaximum(true) .useMultipleOf(true) .useProperties(true) .useAdditionalProperties(true) .usePatternProperties(true) .useDependencies(true) .usePropertyDependencies(true) .useAllOf(true) .useAnyOf(true) .useOneOf(true) .useIfThenElse(true) .useNot(true) .resolveReferences(true) .useDefinitions(true) .useComponents(true) .useFaker(true) .useCustomGenerators(true) .useCustomFormats(true) .useCustomTypes(true) .validateSchema(false) .strictMode(false) .ignoreUnknownFormats(true) .build(); faker = new JsonSchemaFaker(options); } // ==================== BASIC TYPE TESTS ==================== @Test public void testStringGenerationWithAllFeatures() throws Exception { String schema = "{\n" + " \"type\": \"string\",\n" + " \"minLength\": 5,\n" + " \"maxLength\": 20,\n" + " \"pattern\": \"^[A-Za-z]+$\",\n" + " \"format\": \"email\",\n" + " \"enum\": [\"test1@example.com\", \"test2@example.com\"],\n" + " \"default\": \"default@example.com\",\n" + " \"examples\": [\"example1@test.com\", \"example2@test.com\"]\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isTextual()); String value = result.asText(); assertTrue(value.length() >= 5); assertTrue(value.length() <= 20); assertTrue(value.contains("@")); } @Test public void testNumberGenerationWithConstraints() throws Exception { String schema = "{\n" + " \"type\": \"number\",\n" + " \"minimum\": 10.0,\n" + " \"maximum\": 100.0,\n" + " \"exclusiveMinimum\": 10.0,\n" + " \"exclusiveMaximum\": 100.0,\n" + " \"multipleOf\": 5.0,\n" + " \"enum\": [15.0, 25.0, 35.0],\n" + " \"default\": 20.0\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isDouble()); double value = result.asDouble(); assertTrue(value > 10.0); assertTrue(value < 100.0); assertTrue(value % 5.0 == 0.0); } @Test public void testIntegerGenerationWithConstraints() throws Exception { String schema = "{\n" + " \"type\": \"integer\",\n" + " \"minimum\": 1,\n" + " \"maximum\": 100,\n" + " \"exclusiveMinimum\": 1,\n" + " \"exclusiveMaximum\": 100,\n" + " \"multipleOf\": 2,\n" + " \"enum\": [2, 4, 6, 8],\n" + " \"default\": 4\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isInt()); int value = result.asInt(); assertTrue(value > 1); assertTrue(value < 100); assertTrue(value % 2 == 0); } @Test public void testBooleanGeneration() throws Exception { String schema = "{\n" + " \"type\": \"boolean\",\n" + " \"enum\": [true],\n" + " \"default\": false\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isBoolean()); } @Test public void testNullGeneration() throws Exception { String schema = "{\n" + " \"type\": \"null\",\n" + " \"enum\": [null]\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isNull()); } // ==================== ARRAY TESTS ==================== @Test public void testArrayGenerationWithConstraints() throws Exception { String schema = "{\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"email\"\n" + " },\n" + " \"minItems\": 2,\n" + " \"maxItems\": 5,\n" + " \"uniqueItems\": true,\n" + " \"additionalItems\": false\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isArray()); assertTrue(result.size() >= 2); assertTrue(result.size() <= 5); for (JsonNode item : result) { assertTrue(item.isTextual()); assertTrue(item.asText().contains("@")); } } @Test public void testArrayWithTupleValidation() throws Exception { String schema = "{\n" + " \"type\": \"array\",\n" + " \"items\": [\n" + " {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " },\n" + " {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 18,\n" + " \"maximum\": 100\n" + " },\n" + " {\n" + " \"type\": \"string\",\n" + " \"format\": \"email\"\n" + " }\n" + " ],\n" + " \"additionalItems\": {\n" + " \"type\": \"string\"\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isArray()); assertTrue(result.size() >= 3); // Check first item is a name assertTrue(result.get(0).isTextual()); // Check second item is an integer assertTrue(result.get(1).isInt()); int age = result.get(1).asInt(); assertTrue(age >= 18 && age <= 100); // Check third item is an email assertTrue(result.get(2).isTextual()); assertTrue(result.get(2).asText().contains("@")); } @Test public void testArrayWithReferenceItems() throws Exception { String schema = "{\n" + " \"definitions\": {\n" + " \"Person\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"age\": {\n" + " \"type\": \"integer\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/definitions/Person\"\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); System.out.println("Array with reference items result: " + result.toString()); assertNotNull(result); assertTrue(result.isArray()); for (JsonNode person : result) { System.out.println("Person from array: " + person.toString()); assertTrue(person.has("name")); assertTrue(person.has("age")); } } // ==================== OBJECT TESTS ==================== @Test public void testObjectGenerationWithAllFeatures() throws Exception { String schema = "{\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"uuid\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " },\n" + " \"email\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"email\"\n" + " },\n" + " \"age\": {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 18,\n" + " \"maximum\": 100\n" + " },\n" + " \"isActive\": {\n" + " \"type\": \"boolean\"\n" + " },\n" + " \"tags\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"maxItems\": 3\n" + " }\n" + " },\n" + " \"required\": [\"id\", \"name\", \"email\"],\n" + " \"additionalProperties\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"patternProperties\": {\n" + " \"^meta_\": {\n" + " \"type\": \"string\"\n" + " }\n" + " },\n" + " \"dependencies\": {\n" + " \"email\": {\n" + " \"required\": [\"emailVerified\"]\n" + " }\n" + " },\n" + " \"propertyDependencies\": {\n" + " \"email\": [\"emailVerified\"]\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); // Check required properties assertTrue(result.has("id")); assertTrue(result.has("name")); assertTrue(result.has("email")); // Check property types assertTrue(result.get("id").isTextual()); assertTrue(result.get("name").isTextual()); assertTrue(result.get("email").isTextual()); assertTrue(result.get("email").asText().contains("@")); if (result.has("age")) { assertTrue(result.get("age").isInt()); int age = result.get("age").asInt(); assertTrue(age >= 18 && age <= 100); } if (result.has("isActive")) { assertTrue(result.get("isActive").isBoolean()); } if (result.has("tags")) { assertTrue(result.get("tags").isArray()); } } // ==================== ADVANCED SCHEMA TESTS ==================== @Test public void testOneOfGeneration() throws Exception { String schema = "{\n" + " \"oneOf\": [\n" + " {\n" + " \"type\": \"string\",\n" + " \"format\": \"email\"\n" + " },\n" + " {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " ]\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isTextual() || result.isObject()); if (result.isTextual()) { assertTrue(result.asText().contains("@")); } else if (result.isObject()) { assertTrue(result.has("name")); } } @Test public void testAnyOfGeneration() throws Exception { String schema = "{\n" + " \"anyOf\": [\n" + " {\n" + " \"type\": \"string\"\n" + " },\n" + " {\n" + " \"type\": \"integer\"\n" + " }\n" + " ]\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isTextual() || result.isInt()); } @Test public void testAllOfGeneration() throws Exception { String schema = "{\n" + " \"allOf\": [\n" + " {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " },\n" + " {\n" + " \"properties\": {\n" + " \"age\": {\n" + " \"type\": \"integer\"\n" + " }\n" + " }\n" + " }\n" + " ]\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("name")); assertTrue(result.has("age")); assertTrue(result.get("name").isTextual()); assertTrue(result.get("age").isInt()); } @Test public void testIfThenElseGeneration() throws Exception { String schema = "{\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"type\": {\n" + " \"type\": \"string\",\n" + " \"enum\": [\"admin\", \"user\"]\n" + " }\n" + " },\n" + " \"if\": {\n" + " \"properties\": {\n" + " \"type\": {\n" + " \"const\": \"admin\"\n" + " }\n" + " }\n" + " },\n" + " \"then\": {\n" + " \"properties\": {\n" + " \"adminLevel\": {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 1,\n" + " \"maximum\": 10\n" + " }\n" + " }\n" + " },\n" + " \"else\": {\n" + " \"properties\": {\n" + " \"userLevel\": {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 1,\n" + " \"maximum\": 5\n" + " }\n" + " }\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("type")); String type = result.get("type").asText(); if ("admin".equals(type)) { assertTrue(result.has("adminLevel")); assertTrue(result.get("adminLevel").isInt()); } else { assertTrue(result.has("userLevel")); assertTrue(result.get("userLevel").isInt()); } } @Test public void testNotGeneration() throws Exception { String schema = "{\n" + " \"not\": {\n" + " \"type\": \"null\"\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertFalse(result.isNull()); } // ==================== REFERENCE TESTS ==================== @Test public void testReferenceResolution() throws Exception { String schema = "{\n" + " \"definitions\": {\n" + " \"User\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"uuid\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " },\n" + " \"email\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"email\"\n" + " }\n" + " },\n" + " \"required\": [\"id\", \"name\", \"email\"]\n" + " },\n" + " \"Address\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"street\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"city\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"country\": {\n" + " \"type\": \"string\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"user\": {\n" + " \"$ref\": \"#/definitions/User\"\n" + " },\n" + " \"address\": {\n" + " \"$ref\": \"#/definitions/Address\"\n" + " },\n" + " \"role\": {\n" + " \"type\": \"string\",\n" + " \"enum\": [\"admin\", \"user\"]\n" + " }\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("user")); assertTrue(result.has("address")); assertTrue(result.has("role")); JsonNode user = result.get("user"); assertTrue(user.has("id")); assertTrue(user.has("name")); assertTrue(user.has("email")); JsonNode address = result.get("address"); assertTrue(address.has("street")); assertTrue(address.has("city")); assertTrue(address.has("country")); } // ==================== CUSTOM GENERATOR TESTS ==================== @Test public void testCustomFormatGenerator() throws Exception { // Add custom format generator faker.addFormat("custom-format", (schema, opts) -> { return new com.fasterxml.jackson.databind.node.TextNode("custom-generated-value-" + System.currentTimeMillis()); }); String schema = "{\n" + " \"type\": \"string\",\n" + " \"format\": \"custom-format\"\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isTextual()); assertTrue(result.asText().startsWith("custom-generated-value-")); } @Test public void testCustomTypeGenerator() throws Exception { // Add custom type generator faker.addGenerator("custom-type", (schema, opts) -> { ObjectNode node = new ObjectNode(com.fasterxml.jackson.databind.node.JsonNodeFactory.instance); node.put("customField", "customValue"); node.put("timestamp", System.currentTimeMillis()); return node; }); String schema = "{\n" + " \"type\": \"custom-type\"\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("customField")); assertTrue(result.has("timestamp")); assertEquals("customValue", result.get("customField").asText()); } // ==================== MULTITHREADED TESTS ==================== @Test public void testMultithreadedGeneration() throws Exception { String schema = "{\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"uuid\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " },\n" + " \"email\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"email\"\n" + " },\n" + " \"age\": {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 18,\n" + " \"maximum\": 100\n" + " }\n" + " }\n" + "}"; int threadCount = 10; int generationsPerThread = 100; ExecutorService executor = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(threadCount); AtomicInteger successCount = new AtomicInteger(0); AtomicInteger failureCount = new AtomicInteger(0); for (int i = 0; i < threadCount; i++) { final int threadId = i; executor.submit(() -> { try { for (int j = 0; j < generationsPerThread; j++) { try { JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("id")); assertTrue(result.has("name")); assertTrue(result.has("email")); successCount.incrementAndGet(); } catch (Exception e) { failureCount.incrementAndGet(); e.printStackTrace(); } } } finally { latch.countDown(); } }); } latch.await(30, TimeUnit.SECONDS); executor.shutdown(); assertEquals(threadCount * generationsPerThread, successCount.get()); assertEquals(0, failureCount.get()); } @Test public void testMultithreadedCustomGenerators() throws Exception { // Add thread-safe custom generator faker.addGenerator("thread-safe-type", (schema, opts) -> { ObjectNode node = new ObjectNode(com.fasterxml.jackson.databind.node.JsonNodeFactory.instance); node.put("threadId", Thread.currentThread().getId()); node.put("timestamp", System.currentTimeMillis()); node.put("random", Math.random()); return node; }); String schema = "{\n" + " \"type\": \"thread-safe-type\"\n" + "}"; int threadCount = 5; int generationsPerThread = 50; ExecutorService executor = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(threadCount); AtomicBoolean hasErrors = new AtomicBoolean(false); for (int i = 0; i < threadCount; i++) { executor.submit(() -> { try { for (int j = 0; j < generationsPerThread; j++) { try { JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("threadId")); assertTrue(result.has("timestamp")); assertTrue(result.has("random")); } catch (Exception e) { hasErrors.set(true); e.printStackTrace(); } } } finally { latch.countDown(); } }); } latch.await(30, TimeUnit.SECONDS); executor.shutdown(); assertFalse(hasErrors.get(), "Multithreaded custom generator test failed"); } @Test public void testMultithreadedReferenceResolution() throws Exception { String schema = "{\n" + " \"definitions\": {\n" + " \"Person\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " },\n" + " \"age\": {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 1,\n" + " \"maximum\": 120\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/definitions/Person\"\n" + " },\n" + " \"minItems\": 1,\n" + " \"maxItems\": 3\n" + "}"; int threadCount = 8; int generationsPerThread = 75; ExecutorService executor = Executors.newFixedThreadPool(threadCount); CountDownLatch latch = new CountDownLatch(threadCount); AtomicInteger successCount = new AtomicInteger(0); for (int i = 0; i < threadCount; i++) { executor.submit(() -> { try { for (int j = 0; j < generationsPerThread; j++) { try { JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isArray()); assertTrue(result.size() >= 1); assertTrue(result.size() <= 3); for (JsonNode person : result) { assertTrue(person.has("name")); assertTrue(person.has("age")); assertTrue(person.get("name").isTextual()); assertTrue(person.get("age").isInt()); } successCount.incrementAndGet(); } catch (Exception e) { e.printStackTrace(); } } } finally { latch.countDown(); } }); } latch.await(30, TimeUnit.SECONDS); executor.shutdown(); assertEquals(threadCount * generationsPerThread, successCount.get()); } @Test public void testMultithreadedReferenceResolutionDebug() throws Exception { String schema = "{\n" + " \"definitions\": {\n" + " \"Person\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " },\n" + " \"age\": {\n" + " \"type\": \"integer\",\n" + " \"minimum\": 1,\n" + " \"maximum\": 120\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"$ref\": \"#/definitions/Person\"\n" + " },\n" + " \"minItems\": 1,\n" + " \"maxItems\": 3\n" + "}"; // Test single generation first JsonNode result = faker.generate(schema); System.out.println("Single generation result: " + result.toString()); assertNotNull(result); assertTrue(result.isArray()); assertTrue(result.size() >= 1); assertTrue(result.size() <= 3); for (JsonNode person : result) { System.out.println("Person: " + person.toString()); assertTrue(person.has("name")); assertTrue(person.has("age")); assertTrue(person.get("name").isTextual()); assertTrue(person.get("age").isInt()); } } // ==================== EDGE CASE TESTS ==================== @Test public void testEmptySchema() throws Exception { String schema = "{}"; JsonNode result = faker.generate(schema); assertNotNull(result); // Should default to string generation assertTrue(result.isTextual()); } @Test public void testNullSchema() throws Exception { JsonNode result = faker.generate((String) null); assertNotNull(result); assertTrue(result.isNull()); } @Test public void testInvalidSchema() { try { faker.generate("invalid json"); fail("Should throw exception for invalid JSON"); } catch (Exception e) { // Expected } } @Test public void testCircularReference() throws Exception { String schema = "{\n" + " \"definitions\": {\n" + " \"Node\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"value\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"next\": {\n" + " \"$ref\": \"#/definitions/Node\"\n" + " }\n" + " }\n" + " }\n" + " },\n" + " \"$ref\": \"#/definitions/Node\"\n" + "}"; // This should not cause infinite recursion JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); } @Test public void testLargeArrayGeneration() throws Exception { String schema = "{\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"type\": \"string\"\n" + " },\n" + " \"minItems\": 100,\n" + " \"maxItems\": 100\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isArray()); assertEquals(100, result.size()); for (JsonNode item : result) { assertTrue(item.isTextual()); } } @Test public void testComplexNestedObject() throws Exception { String schema = "{\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"users\": {\n" + " \"type\": \"array\",\n" + " \"items\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"profile\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"settings\": {\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"theme\": {\n" + " \"type\": \"string\",\n" + " \"enum\": [\"light\", \"dark\"]\n" + " },\n" + " \"notifications\": {\n" + " \"type\": \"boolean\"\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + " }\n" + "}"; JsonNode result = faker.generate(schema); assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("users")); JsonNode users = result.get("users"); assertTrue(users.isArray()); for (JsonNode user : users) { assertTrue(user.has("profile")); JsonNode profile = user.get("profile"); assertTrue(profile.has("settings")); JsonNode settings = profile.get("settings"); assertTrue(settings.has("theme") || settings.has("notifications")); } } // ==================== PERFORMANCE TESTS ==================== @Test public void testPerformanceWithLargeSchema() throws Exception { StringBuilder schemaBuilder = new StringBuilder(); schemaBuilder.append("{\n"); schemaBuilder.append(" \"type\": \"object\",\n"); schemaBuilder.append(" \"properties\": {\n"); // Add 100 properties for (int i = 0; i < 100; i++) { schemaBuilder.append(" \"field").append(i).append("\": {\n"); schemaBuilder.append(" \"type\": \"string\",\n"); schemaBuilder.append(" \"format\": \"email\"\n"); schemaBuilder.append(" }"); if (i < 99) schemaBuilder.append(","); schemaBuilder.append("\n"); } schemaBuilder.append(" }\n"); schemaBuilder.append("}"); String schema = schemaBuilder.toString(); long startTime = System.currentTimeMillis(); JsonNode result = faker.generate(schema); long endTime = System.currentTimeMillis(); assertNotNull(result); assertTrue(result.isObject()); // Should complete within 5 seconds assertTrue((endTime - startTime) < 5000, "Generation took too long: " + (endTime - startTime) + "ms"); } @Test public void testBatchGenerationPerformance() throws Exception { String schema = "{\n" + " \"type\": \"object\",\n" + " \"properties\": {\n" + " \"id\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"uuid\"\n" + " },\n" + " \"name\": {\n" + " \"type\": \"string\",\n" + " \"format\": \"name\"\n" + " }\n" + " }\n" + "}"; long startTime = System.currentTimeMillis(); JsonNode[] results = faker.generateMultiple(schema, 1000); long endTime = System.currentTimeMillis(); assertEquals(1000, results.length); for (JsonNode result : results) { assertNotNull(result); assertTrue(result.isObject()); assertTrue(result.has("id")); assertTrue(result.has("name")); } // Should complete within 10 seconds assertTrue((endTime - startTime) < 10000, "Batch generation took too long: " + (endTime - startTime) + "ms"); } }