From 0624c3a5977bc9fe033d72a7005b5000e1a80e2f Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 8 Jan 2026 13:15:53 +0100 Subject: [PATCH] Introduce tests for non-generic types for PropertyDescriptorUtils This commit introduces tests for proper support for non-generic types in PropertyDescriptorUtils.determineBasicProperties(), effectively to test the status quo and serve as regression tests. --- ...escriptorUtilsPropertyResolutionTests.java | 185 +++++++++++++++++- 1 file changed, 175 insertions(+), 10 deletions(-) diff --git a/spring-beans/src/test/java/org/springframework/beans/PropertyDescriptorUtilsPropertyResolutionTests.java b/spring-beans/src/test/java/org/springframework/beans/PropertyDescriptorUtilsPropertyResolutionTests.java index 5b0e1775e20..c18b714e448 100644 --- a/spring-beans/src/test/java/org/springframework/beans/PropertyDescriptorUtilsPropertyResolutionTests.java +++ b/spring-beans/src/test/java/org/springframework/beans/PropertyDescriptorUtilsPropertyResolutionTests.java @@ -60,6 +60,161 @@ class PropertyDescriptorUtilsPropertyResolutionTests { PropertiesResolver resolver; + @Nested + class NonGenericTypesTests { + + @Test + void classWithOnlyGetter() { + var pdMap = resolver.resolve(ClassWithOnlyGetter.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, Number.class, null); + } + + @Test + void classWithOnlySetter() { + var pdMap = resolver.resolve(ClassWithOnlySetter.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, null, Long.class); + } + + @Test + void classWithMatchingGetterAndSetter() { + var pdMap = resolver.resolve(ClassWithMatchingGetterAndSetter.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, Long.class, Long.class); + } + + @Test + void classWithOneUnrelatedSetter() { + var pdMap = resolver.resolve(ClassWithOneUnrelatedSetter.class); + + // java.beans.Introspector never resolves unrelated write methods. + Class writeType = null; + if (resolver instanceof BasicPropertiesResolver) { + // Spring resolves a single write method even if its type is not + // related to the read type. + writeType = String.class; + } + + assertReadAndWriteMethodsForClassAndId(pdMap, Integer.class, writeType); + } + + @Test + void classWithUnrelatedSettersInSameTypeHierarchy() { + var pdMap = resolver.resolve(ClassWithUnrelatedSettersInSameTypeHierarchy.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, Integer.class, null); + } + + @Test + void classWithOneSubtypeSetter() { + var pdMap = resolver.resolve(ClassWithOneSubtypeSetter.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, Number.class, Long.class); + } + + @Test + void classWithTwoSubtypeSetters() { + var pdMap = resolver.resolve(ClassWithTwoSubtypeSetters.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, Serializable.class, Long.class); + } + + @Test + void classWithTwoSubtypeSettersAndOneUnrelatedSetter() { + var pdMap = resolver.resolve(ClassWithTwoSubtypeSettersAndOneUnrelatedSetter.class); + + assertReadAndWriteMethodsForClassAndId(pdMap, Serializable.class, Long.class); + } + + + static class ClassWithOnlyGetter { + + public Number getId() { + return 42; + } + } + + static class ClassWithOnlySetter { + + public void setId(Long id) { + } + } + + static class ClassWithMatchingGetterAndSetter { + + public Long getId() { + return 42L; + } + + public void setId(Long id) { + } + } + + static class ClassWithOneUnrelatedSetter { + + public Integer getId() { + return 42; + } + + public void setId(String id) { + } + } + + static class ClassWithUnrelatedSettersInSameTypeHierarchy { + + public Integer getId() { + return 42; + } + + public void setId(CharSequence id) { + } + + public void setId(String id) { + } + } + + static class ClassWithOneSubtypeSetter { + + public Number getId() { + return 42; + } + + public void setId(Long id) { + } + } + + static class ClassWithTwoSubtypeSetters { + + public Serializable getId() { + return 42; + } + + public void setId(Number id) { + } + + public void setId(Long id) { + } + } + + static class ClassWithTwoSubtypeSettersAndOneUnrelatedSetter { + + public Serializable getId() { + return 42; + } + + public void setId(Number id) { + } + + public void setId(Long id) { + } + + public void setId(String id) { + } + } + } + + @Nested class UnboundedGenericsTests { @@ -205,16 +360,26 @@ class PropertyDescriptorUtilsPropertyResolutionTests { var writeMethod = pd.getWriteMethod(); assertSoftly(softly -> { - softly.assertThat(readMethod.getName()).isEqualTo("getId"); - softly.assertThat(readMethod.getReturnType()).as("read type").isEqualTo(readType); - softly.assertThat(readMethod.getParameterCount()).isZero(); - - softly.assertThat(writeMethod).as("write method").isNotNull(); - if (writeMethod != null) { - softly.assertThat(writeMethod.getName()).isEqualTo("setId"); - softly.assertThat(writeMethod.getReturnType()).isEqualTo(void.class); - softly.assertThat(writeMethod.getParameterCount()).isEqualTo(1); - softly.assertThat(writeMethod.getParameterTypes()[0]).as("write type").isEqualTo(writeType); + if (readType == null) { + softly.assertThat(readMethod).as("readmethod").isNull(); + } + else { + softly.assertThat(readMethod.getName()).isEqualTo("getId"); + softly.assertThat(readMethod.getReturnType()).as("read type").isEqualTo(readType); + softly.assertThat(readMethod.getParameterCount()).isZero(); + } + + if (writeType == null) { + softly.assertThat(writeMethod).as("write method").isNull(); + } + else { + softly.assertThat(writeMethod).as("write method").isNotNull(); + if (writeMethod != null) { + softly.assertThat(writeMethod.getName()).isEqualTo("setId"); + softly.assertThat(writeMethod.getReturnType()).isEqualTo(void.class); + softly.assertThat(writeMethod.getParameterCount()).isEqualTo(1); + softly.assertThat(writeMethod.getParameterTypes()[0]).as("write type").isEqualTo(writeType); + } } }); }