@@ -10936,4 +10936,138 @@ public void javaCamelStillGeneratesClasses() throws IOException {
1093610936
1093710937 JavaFileAssert.assertThat(files.get("Pet.java")).isNormalClass().fileDoesNotContain("record");
1093810938 }
10939+
10940+ private static final String RECORDS_MODEL_DEFAULTS_SPEC = "src/test/resources/3_0/spring/records-model-defaults.yaml";
10941+
10942+ @Test
10943+ public void useRecordsKeepsModelConstructedByDefaultAsClass() throws IOException {
10944+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
10945+
10946+ assertSource(files, "Sub.java").contains("public class Sub {").doesNotContain("public record Sub(");
10947+ assertSource(files, "Holder.java").contains("public record Holder(", " inner = new Sub();");
10948+ }
10949+
10950+ @Test
10951+ public void useRecordsLogsWhyModelConstructedByDefaultIsAClass() {
10952+ List<String> messages = captureLogMessages(SpringCodegen.class, () -> {
10953+ try {
10954+ generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
10955+ } catch (IOException e) {
10956+ throw new RuntimeException(e);
10957+ }
10958+ });
10959+
10960+ assertThat(messages).contains(
10961+ "useRecords: model 'Sub' is generated as a class: the default of property 'inner' in model 'Holder' constructs it with new Sub()");
10962+ }
10963+
10964+ @Test
10965+ public void useRecordsKeepsModelWithNonEmptyDefaultAsClass() throws IOException {
10966+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
10967+
10968+ assertSource(files, "Named.java").contains("public class Named {");
10969+ assertSource(files, "Holder.java").contains(" named = new Named().x(\"a\");");
10970+ }
10971+
10972+ @Test
10973+ public void useRecordsKeepsEveryModelOfNestedDefaultAsClass() throws IOException {
10974+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
10975+
10976+ assertSource(files, "Outer.java").contains("public class Outer {");
10977+ assertSource(files, "Leaf.java").contains("public class Leaf {");
10978+ assertSource(files, "Holder.java").contains("new Outer().inner(new Leaf().v(\"r\"))");
10979+ }
10980+
10981+ @Test
10982+ public void useRecordsKeepsModelInListAndSetDefaultAsClass() throws IOException {
10983+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
10984+
10985+ assertSource(files, "ListItem.java").contains("public class ListItem {");
10986+ assertSource(files, "SetItem.java").contains("public class SetItem {");
10987+ assertSource(files, "Holder.java").contains(
10988+ " items = new ArrayList<>(Arrays.asList(new ListItem()));",
10989+ " uniqueItems = new LinkedHashSet<>(Arrays.asList(new SetItem()));");
10990+ }
10991+
10992+ @Test
10993+ public void useRecordsKeepsModelWithoutPropertiesAsRecord() throws IOException {
10994+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
10995+
10996+ assertSource(files, "Hollow.java").contains("public record Hollow(");
10997+ assertSource(files, "Holder.java").contains(" hollow = new Hollow();");
10998+ }
10999+
11000+ @Test
11001+ public void useRecordsKeepsOriginalReasonOfModelThatAlreadyStaysClass() {
11002+ List<String> messages = captureLogMessages(SpringCodegen.class, () -> {
11003+ try {
11004+ generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
11005+ } catch (IOException e) {
11006+ throw new RuntimeException(e);
11007+ }
11008+ });
11009+
11010+ assertThat(messages).contains("useRecords: model 'LooseSub' is generated as a class: it has additionalProperties");
11011+ assertThat(messages).noneMatch(m -> m.contains("model 'LooseSub'") && m.contains("constructs it"));
11012+ }
11013+
11014+ @Test
11015+ public void useRecordsIgnoresStringDefaultThatLooksLikeConstructor() throws IOException {
11016+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
11017+
11018+ assertSource(files, "Untouched.java").contains("public record Untouched(");
11019+ assertSource(files, "Holder.java").contains(" text = \"new Untouched()\";");
11020+ }
11021+
11022+ @Test
11023+ public void useRecordsOffKeepsModelDefaultsAsClasses() throws IOException {
11024+ Map<String, File> files = generateFromContract(RECORDS_MODEL_DEFAULTS_SPEC, SPRING_BOOT);
11025+
11026+ JavaFileAssert.assertThat(files.get("Holder.java"))
11027+ .isNormalClass()
11028+ .fileContains("private Sub inner = new Sub();", "private Named named = new Named().x(\"a\");");
11029+ JavaFileAssert.assertThat(files.get("Untouched.java")).isNormalClass();
11030+ }
11031+
11032+ @Test
11033+ public void useRecordsKeepsNullableModelWithDefaultAsRecord() throws IOException {
11034+ List<String> messages = captureLogMessages(SpringCodegen.class, () -> {
11035+ try {
11036+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of());
11037+ assertSource(files, "Quiet.java").contains("public record Quiet(");
11038+ assertSource(files, "QuietItem.java").contains("public record QuietItem(");
11039+ assertSource(files, "Holder.java").contains(
11040+ " quiet = JsonNullable.<Quiet>undefined();",
11041+ " quietItems = JsonNullable.<List<@Valid QuietItem>>undefined();");
11042+ } catch (IOException e) {
11043+ throw new RuntimeException(e);
11044+ }
11045+ });
11046+
11047+ assertThat(messages).noneMatch(m -> m.contains("model 'Quiet'") || m.contains("model 'QuietItem'"));
11048+ }
11049+
11050+ @Test
11051+ public void useRecordsKeepsModelInNullableContainerDefaultAsClassWithoutOpenApiNullable() throws IOException {
11052+ Map<String, File> files = generateRecords(RECORDS_MODEL_DEFAULTS_SPEC, Map.of(CodegenConstants.OPENAPI_NULLABLE, "false"));
11053+
11054+ // a nullable property that is not a container is initialised with null, a nullable container with its default
11055+ assertSource(files, "Quiet.java").contains("public record Quiet(");
11056+ assertSource(files, "QuietItem.java").contains("public class QuietItem {");
11057+ assertSource(files, "Holder.java").contains(" quietItems = new ArrayList<>(Arrays.asList(new QuietItem()));");
11058+ }
11059+
11060+ @Test
11061+ public void useRecordsLogsNoModelThatHasNoFile() throws IOException {
11062+ List<String> messages = captureLogMessages(SpringCodegen.class, () -> {
11063+ try {
11064+ Map<String, File> files = generateRecords("src/test/resources/3_0/spring/records-model-defaults-jdk-names.yaml", Map.of());
11065+ assertThat(files).doesNotContainKey("URI.java");
11066+ } catch (IOException e) {
11067+ throw new RuntimeException(e);
11068+ }
11069+ });
11070+
11071+ assertThat(messages).noneMatch(m -> m.contains("model 'URI'"));
11072+ }
1093911073}
0 commit comments