1+ package com .redis .om .spring .repository ;
2+
3+ import com .redis .om .spring .AbstractBaseDocumentTest ;
4+ import com .redis .om .spring .fixtures .document .model .DocumentWithMixedTypes ;
5+ import com .redis .om .spring .fixtures .document .repository .DocumentMixedTypesProjection ;
6+ import com .redis .om .spring .fixtures .document .repository .DocumentMixedTypesProjectionFixed ;
7+ import com .redis .om .spring .fixtures .document .repository .DocumentMixedTypesRepository ;
8+ import org .junit .jupiter .api .AfterEach ;
9+ import org .junit .jupiter .api .BeforeEach ;
10+ import org .junit .jupiter .api .Test ;
11+ import org .springframework .beans .factory .annotation .Autowired ;
12+
13+ import java .time .LocalDate ;
14+ import java .util .Optional ;
15+
16+ import static org .junit .jupiter .api .Assertions .*;
17+
18+ /**
19+ * Test to reproduce and demonstrate issue #650:
20+ * Projection interfaces return null for non-String fields when not using @Value annotation
21+ */
22+ class DocumentProjectionMixedTypesTest extends AbstractBaseDocumentTest {
23+
24+ @ Autowired
25+ private DocumentMixedTypesRepository repository ;
26+
27+ private DocumentWithMixedTypes testEntity ;
28+
29+ @ BeforeEach
30+ void setUp () {
31+ testEntity = DocumentWithMixedTypes .builder ()
32+ .name ("John Doe" )
33+ .age (30 )
34+ .salary (75000.50 )
35+ .active (true )
36+ .birthDate (LocalDate .of (1993 , 5 , 15 ))
37+ .description ("Test employee" )
38+ .build ();
39+
40+ testEntity = repository .save (testEntity );
41+ }
42+
43+ @ Test
44+ void testEntityFetch_VerifyDataExists () {
45+ // First verify the entity exists with proper data
46+ Optional <DocumentWithMixedTypes > entity = repository .findByName ("John Doe" );
47+
48+ assertTrue (entity .isPresent (), "Entity should be found by name" );
49+ assertEquals ("John Doe" , entity .get ().getName ());
50+ assertEquals (30 , entity .get ().getAge ());
51+ assertEquals (75000.50 , entity .get ().getSalary ());
52+ assertTrue (entity .get ().getActive ());
53+ assertEquals (LocalDate .of (1993 , 5 , 15 ), entity .get ().getBirthDate ());
54+ }
55+
56+ @ Test
57+ void testProjectionWithoutValueAnnotation_NonStringFieldsReturnNull () {
58+ // This test demonstrates the issue - non-String fields return null without @Value
59+ Optional <DocumentMixedTypesProjection > projection = repository .findFirstByName ("John Doe" );
60+
61+ assertTrue (projection .isPresent (), "Projection should be present" );
62+
63+ // String field should work
64+ assertEquals ("John Doe" , projection .get ().getName (), "String field should work without @Value" );
65+
66+ // These assertions demonstrate the issue - all non-String fields return null
67+ assertNull (projection .get ().getAge (),
68+ "Integer field returns null without @Value annotation - this is the issue!" );
69+ assertNull (projection .get ().getSalary (),
70+ "Double field returns null without @Value annotation - this is the issue!" );
71+ assertNull (projection .get ().getActive (),
72+ "Boolean field returns null without @Value annotation - this is the issue!" );
73+ assertNull (projection .get ().getBirthDate (),
74+ "LocalDate field returns null without @Value annotation - this is the issue!" );
75+ }
76+
77+ @ Test
78+ void testProjectionWithValueAnnotation_AllFieldsWork () {
79+ // Test that all fields work correctly with @Value annotation (the workaround)
80+ Optional <DocumentMixedTypesProjectionFixed > projection = repository .findOneByName ("John Doe" );
81+
82+ assertTrue (projection .isPresent (), "Projection should be present" );
83+
84+ // All fields should work with @Value annotation
85+ assertEquals ("John Doe" , projection .get ().getName (), "String field should work" );
86+ assertEquals (30 , projection .get ().getAge (), "Integer field should work with @Value" );
87+ assertEquals (75000.50 , projection .get ().getSalary (), "Double field should work with @Value" );
88+ assertTrue (projection .get ().getActive (), "Boolean field should work with @Value" );
89+ assertEquals (LocalDate .of (1993 , 5 , 15 ), projection .get ().getBirthDate (),
90+ "LocalDate field should work with @Value" );
91+ }
92+
93+ @ Test
94+ void testDirectEntityFetch_AllFieldsWork () {
95+ // Verify that the entity itself has all fields correctly stored
96+ Optional <DocumentWithMixedTypes > entity = repository .findById (testEntity .getId ());
97+
98+ assertTrue (entity .isPresent (), "Entity should be present" );
99+ assertEquals ("John Doe" , entity .get ().getName ());
100+ assertEquals (30 , entity .get ().getAge ());
101+ assertEquals (75000.50 , entity .get ().getSalary ());
102+ assertTrue (entity .get ().getActive ());
103+ assertEquals (LocalDate .of (1993 , 5 , 15 ), entity .get ().getBirthDate ());
104+ }
105+
106+ @ AfterEach
107+ void tearDown () {
108+ repository .deleteAll ();
109+ }
110+ }
0 commit comments