1+ package de .tum .team_sigma .document_service .integration ;
2+
3+ import io .minio .*;
4+ import io .minio .errors .ErrorResponseException ;
5+ import io .weaviate .client .WeaviateClient ;
6+ import io .weaviate .client .base .Result ;
7+ import io .weaviate .client .v1 .data .model .WeaviateObject ;
8+ import io .weaviate .client .v1 .schema .model .Property ;
9+ import io .weaviate .client .v1 .schema .model .WeaviateClass ;
10+ import org .junit .jupiter .api .Test ;
11+ import org .junit .jupiter .api .BeforeAll ;
12+ import org .junit .jupiter .api .Disabled ;
13+ import org .springframework .beans .factory .annotation .Autowired ;
14+ import org .springframework .boot .test .context .SpringBootTest ;
15+ import org .springframework .test .context .ActiveProfiles ;
16+ import org .springframework .test .context .DynamicPropertyRegistry ;
17+ import org .springframework .test .context .DynamicPropertySource ;
18+ import org .testcontainers .containers .MinIOContainer ;
19+ import org .testcontainers .junit .jupiter .Container ;
20+ import org .testcontainers .junit .jupiter .Testcontainers ;
21+ import org .testcontainers .weaviate .WeaviateContainer ;
22+
23+ import java .io .ByteArrayInputStream ;
24+ import java .nio .charset .StandardCharsets ;
25+ import java .util .Map ;
26+ import java .util .UUID ;
27+
28+ import static org .junit .jupiter .api .Assertions .*;
29+
30+ /**
31+ * Integration tests that require real MinIO and Weaviate containers.
32+ * These tests are disabled by default due to longer startup times.
33+ * Enable with @EnabledIf or remove @Disabled to run.
34+ */
35+ @ Testcontainers
36+ @ SpringBootTest (webEnvironment = SpringBootTest .WebEnvironment .NONE )
37+ @ ActiveProfiles ("test" )
38+ @ Disabled ("Enable manually when testing with real containers" )
39+ class ContainerIntegrationTest {
40+
41+ private static final String TEST_BUCKET = "testbucket" ;
42+
43+ @ Container
44+ static final MinIOContainer MINIO = new MinIOContainer ("minio/minio:RELEASE.2023-09-04T19-57-37Z" );
45+
46+ @ Container
47+ static final WeaviateContainer WEAVIATE = new WeaviateContainer ("cr.weaviate.io/semitechnologies/weaviate:1.25.5" );
48+
49+ @ DynamicPropertySource
50+ static void registerProperties (DynamicPropertyRegistry registry ) {
51+ registry .add ("minio.url" , MINIO ::getS3URL );
52+ registry .add ("minio.access-key" , MINIO ::getUserName );
53+ registry .add ("minio.secret-key" , MINIO ::getPassword );
54+ registry .add ("minio.bucket-name" , () -> TEST_BUCKET );
55+ registry .add ("weaviate.url" , () -> WEAVIATE .getHost () + ":" + WEAVIATE .getMappedPort (8080 ));
56+ }
57+
58+ @ Autowired
59+ private MinioClient minioClient ;
60+
61+ @ Autowired
62+ private WeaviateClient weaviateClient ;
63+
64+ @ BeforeAll
65+ void setUp () throws Exception {
66+ // Create test bucket in MinIO
67+ boolean found = minioClient .bucketExists (BucketExistsArgs .builder ().bucket (TEST_BUCKET ).build ());
68+ if (!found ) {
69+ minioClient .makeBucket (MakeBucketArgs .builder ().bucket (TEST_BUCKET ).build ());
70+ }
71+ }
72+
73+ /* ----------------- MinIO Integration Tests ----------------- */
74+ @ Test
75+ void minioShouldPutAndRemoveObject () throws Exception {
76+ String objectKey = "integration/hello.txt" ;
77+ byte [] data = "Hello, MinIO!" .getBytes (StandardCharsets .UTF_8 );
78+
79+ // Upload object
80+ minioClient .putObject (
81+ PutObjectArgs .builder ()
82+ .bucket (TEST_BUCKET )
83+ .object (objectKey )
84+ .stream (new ByteArrayInputStream (data ), data .length , -1 )
85+ .contentType ("text/plain" )
86+ .build ()
87+ );
88+
89+ // Verify exists
90+ StatObjectResponse stat = minioClient .statObject (
91+ StatObjectArgs .builder ().bucket (TEST_BUCKET ).object (objectKey ).build ()
92+ );
93+ assertNotNull (stat );
94+ assertEquals (data .length , stat .size ());
95+
96+ // Download and verify content
97+ try (var inputStream = minioClient .getObject (
98+ GetObjectArgs .builder ().bucket (TEST_BUCKET ).object (objectKey ).build ())) {
99+ String content = new String (inputStream .readAllBytes (), StandardCharsets .UTF_8 );
100+ assertEquals ("Hello, MinIO!" , content );
101+ }
102+
103+ // Delete object
104+ minioClient .removeObject (
105+ RemoveObjectArgs .builder ().bucket (TEST_BUCKET ).object (objectKey ).build ()
106+ );
107+
108+ // Expect deletion
109+ assertThrows (ErrorResponseException .class , () ->
110+ minioClient .statObject (
111+ StatObjectArgs .builder ().bucket (TEST_BUCKET ).object (objectKey ).build ()
112+ ));
113+ }
114+
115+ /* ----------------- Weaviate Integration Tests ----------------- */
116+ @ Test
117+ void weaviateShouldInsertAndDeleteObject () {
118+ String className = "TestEntity" ;
119+ String id = UUID .randomUUID ().toString ();
120+
121+ // Ensure class exists (idempotent)
122+ try {
123+ WeaviateClass clazz = WeaviateClass .builder ()
124+ .className (className )
125+ .vectorizer ("none" )
126+ .properties (java .util .List .of (
127+ Property .builder ()
128+ .name ("text" )
129+ .dataType (java .util .List .of ("text" ))
130+ .build ()
131+ ))
132+ .build ();
133+ weaviateClient .schema ().classCreator ().withClass (clazz ).run ();
134+ } catch (Exception ignored ) {
135+ // class may already exist; ignore
136+ }
137+
138+ Float [] vector = new Float []{0.1f , 0.2f , 0.3f , 0.4f , 0.5f };
139+
140+ // Insert object
141+ Result <WeaviateObject > createResult = weaviateClient .data ().creator ()
142+ .withClassName (className )
143+ .withID (id )
144+ .withVector (vector )
145+ .withProperties (Map .of ("text" , "hello world" ))
146+ .run ();
147+ assertFalse (createResult .hasErrors (), "Object creation should succeed: " + createResult .getError ());
148+
149+ // Retrieve object
150+ Result <java .util .List <WeaviateObject >> getResult = weaviateClient .data ().objectsGetter ()
151+ .withID (id )
152+ .run ();
153+ assertFalse (getResult .hasErrors (), "Object retrieval should succeed: " + getResult .getError ());
154+ assertEquals (1 , getResult .getResult ().size (), "Should retrieve exactly one object" );
155+
156+ // Verify the retrieved object
157+ WeaviateObject retrievedObject = getResult .getResult ().get (0 );
158+ assertEquals (id , retrievedObject .getId ());
159+ assertEquals ("hello world" , retrievedObject .getProperties ().get ("text" ));
160+
161+ // Delete object
162+ Result <Boolean > deleteResult = weaviateClient .data ().deleter ()
163+ .withID (id )
164+ .withClassName (className )
165+ .run ();
166+ assertFalse (deleteResult .hasErrors (), "Deletion should succeed: " + deleteResult .getError ());
167+ assertTrue (deleteResult .getResult (), "Deletion result should be true" );
168+
169+ // Confirm deletion (should return empty list)
170+ Result <java .util .List <WeaviateObject >> afterDelete = weaviateClient .data ().objectsGetter ()
171+ .withID (id )
172+ .run ();
173+ assertTrue (afterDelete .getResult () == null || afterDelete .getResult ().isEmpty (),
174+ "Object should no longer exist" );
175+ }
176+ }
0 commit comments