Skip to content

Commit bedda4a

Browse files
committed
test: adapter tests
1 parent 9f5438e commit bedda4a

7 files changed

Lines changed: 2270 additions & 29 deletions
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
package fr.insee.genesis.infrastructure.adapter;
2+
3+
import fr.insee.genesis.domain.model.extraction.json.LastJsonExtractionModel;
4+
import fr.insee.genesis.domain.model.surveyunit.Mode;
5+
import fr.insee.genesis.exceptions.GenesisException;
6+
import fr.insee.genesis.infrastructure.document.extraction.json.LastJsonExtractionDocument;
7+
import fr.insee.genesis.infrastructure.repository.LastJsonExtractionMongoDBRepository;
8+
import org.junit.jupiter.api.DisplayName;
9+
import org.junit.jupiter.api.Nested;
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.ExtendWith;
12+
import org.mockito.ArgumentCaptor;
13+
import org.mockito.InjectMocks;
14+
import org.mockito.Mock;
15+
import org.mockito.junit.jupiter.MockitoExtension;
16+
17+
import java.util.Optional;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
21+
import static org.mockito.ArgumentMatchers.any;
22+
import static org.mockito.Mockito.verify;
23+
import static org.mockito.Mockito.verifyNoMoreInteractions;
24+
import static org.mockito.Mockito.when;
25+
26+
@ExtendWith(MockitoExtension.class)
27+
@DisplayName("LastJsonExtractionMongoAdapter tests")
28+
class LastJsonExtractionMongoAdapterTest {
29+
30+
private static final String COLLECTION_INSTRUMENT_ID = "instrument-123";
31+
private static final Mode MODE = Mode.WEB;
32+
// Expected id format: "{collectionInstrumentId}_{mode}"
33+
private static final String EXPECTED_ID = "instrument-123_WEB";
34+
35+
@Mock
36+
private LastJsonExtractionMongoDBRepository extractionRepository;
37+
38+
@InjectMocks
39+
private LastJsonExtractionMongoAdapter adapter;
40+
41+
@Nested
42+
@DisplayName("save() tests")
43+
class SaveTests {
44+
45+
@Test
46+
@DisplayName("save() should call repository.save() with a non-null document")
47+
void save_shouldCallRepositorySave() {
48+
//GIVEN
49+
LastJsonExtractionModel model = buildModel();
50+
51+
//WHEN
52+
adapter.save(model);
53+
54+
//THEN
55+
verify(extractionRepository).save(any(LastJsonExtractionDocument.class));
56+
verifyNoMoreInteractions(extractionRepository);
57+
}
58+
59+
@Test
60+
@DisplayName("save() should map the model to a document before persisting")
61+
void save_shouldMapModelToDocument() {
62+
//GIVEN
63+
LastJsonExtractionModel model = buildModel();
64+
65+
//WHEN
66+
adapter.save(model);
67+
68+
//THEN
69+
ArgumentCaptor<LastJsonExtractionDocument> captor = ArgumentCaptor.forClass(LastJsonExtractionDocument.class);
70+
verify(extractionRepository).save(captor.capture());
71+
assertThat(captor.getValue()).isNotNull();
72+
}
73+
}
74+
75+
@Nested
76+
@DisplayName("getLastExecutionDate() tests")
77+
class GetLastExecutionDateTests {
78+
79+
@Test
80+
@DisplayName("Should return mapped model when document is found")
81+
void getLastExecutionDate_found_shouldReturnModel() throws GenesisException {
82+
//GIVEN
83+
LastJsonExtractionDocument doc = new LastJsonExtractionDocument();
84+
when(extractionRepository.findById(EXPECTED_ID)).thenReturn(Optional.of(doc));
85+
86+
//WHEN
87+
LastJsonExtractionModel result = adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, MODE);
88+
89+
//THEN
90+
assertThat(result).isNotNull();
91+
verify(extractionRepository).findById(EXPECTED_ID);
92+
}
93+
94+
@Test
95+
@DisplayName("Should throw GenesisException with 404 status when document is not found")
96+
void getLastExecutionDate_notFound_shouldThrow404() {
97+
//GIVEN
98+
when(extractionRepository.findById(EXPECTED_ID)).thenReturn(Optional.empty());
99+
100+
//WHEN + THEN
101+
assertThatThrownBy(() -> adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, MODE))
102+
.isInstanceOf(GenesisException.class)
103+
.satisfies(ex -> {
104+
GenesisException genesisException = (GenesisException) ex;
105+
assertThat(genesisException.getStatus()).isEqualTo(404);
106+
});
107+
}
108+
109+
@Test
110+
@DisplayName("Should include collectionInstrumentId in exception message when not found")
111+
void getLastExecutionDate_notFound_exceptionMessageShouldContainInstrumentId() {
112+
//GIVEN
113+
when(extractionRepository.findById(EXPECTED_ID)).thenReturn(Optional.empty());
114+
115+
//WHEN + THEN
116+
assertThatThrownBy(() -> adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, MODE))
117+
.isInstanceOf(GenesisException.class)
118+
.hasMessageContaining(COLLECTION_INSTRUMENT_ID);
119+
}
120+
121+
@Test
122+
@DisplayName("Should include mode name in exception message when not found")
123+
void getLastExecutionDate_notFound_exceptionMessageShouldContainModeName() {
124+
//GIVEN
125+
when(extractionRepository.findById(EXPECTED_ID)).thenReturn(Optional.empty());
126+
127+
//WHEN + THEN
128+
assertThatThrownBy(() -> adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, MODE))
129+
.isInstanceOf(GenesisException.class)
130+
.hasMessageContaining(MODE.getModeName());
131+
}
132+
133+
@Test
134+
@DisplayName("Should query repository with id formatted as '{collectionInstrumentId}_{mode}'")
135+
void getLastExecutionDate_shouldUseCorrectIdFormat() throws GenesisException {
136+
//GIVEN
137+
LastJsonExtractionDocument doc = new LastJsonExtractionDocument();
138+
when(extractionRepository.findById(EXPECTED_ID)).thenReturn(Optional.of(doc));
139+
140+
//WHEN
141+
adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, MODE);
142+
143+
//THEN
144+
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
145+
verify(extractionRepository).findById(captor.capture());
146+
assertThat(captor.getValue()).isEqualTo(EXPECTED_ID);
147+
}
148+
149+
@Test
150+
@DisplayName("Should handle null mode — id should be '{collectionInstrumentId}_null'")
151+
void getLastExecutionDate_nullMode_shouldUseNullInId() {
152+
//GIVEN
153+
String expectedIdWithNullMode = "instrument-123_null";
154+
when(extractionRepository.findById(expectedIdWithNullMode)).thenReturn(Optional.empty());
155+
156+
//WHEN + THEN
157+
assertThatThrownBy(() -> adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, null))
158+
.isInstanceOf(GenesisException.class)
159+
.satisfies(ex -> assertThat(((GenesisException) ex).getStatus()).isEqualTo(404));
160+
161+
verify(extractionRepository).findById(expectedIdWithNullMode);
162+
}
163+
164+
@Test
165+
@DisplayName("Exception message should contain 'null' for mode name when mode is null")
166+
void getLastExecutionDate_nullMode_exceptionMessageShouldContainNull() {
167+
//GIVEN
168+
String expectedIdWithNullMode = "instrument-123_null";
169+
when(extractionRepository.findById(expectedIdWithNullMode)).thenReturn(Optional.empty());
170+
171+
//WHEN + THEN
172+
assertThatThrownBy(() -> adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, null))
173+
.isInstanceOf(GenesisException.class)
174+
.hasMessageContaining("null");
175+
}
176+
}
177+
178+
@Nested
179+
@DisplayName("delete() tests")
180+
class DeleteTests {
181+
182+
@Test
183+
@DisplayName("delete() should call repository.deleteById() with the correct id")
184+
void delete_shouldCallDeleteById() {
185+
//WHEN
186+
adapter.delete(COLLECTION_INSTRUMENT_ID, MODE);
187+
188+
//THEN
189+
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
190+
verify(extractionRepository).deleteById(captor.capture());
191+
assertThat(captor.getValue()).isEqualTo(EXPECTED_ID);
192+
verifyNoMoreInteractions(extractionRepository);
193+
}
194+
195+
@Test
196+
@DisplayName("delete() with null mode should use 'null' in the id")
197+
void delete_nullMode_shouldUseNullInId() {
198+
//WHEN
199+
adapter.delete(COLLECTION_INSTRUMENT_ID, null);
200+
201+
//THEN
202+
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
203+
verify(extractionRepository).deleteById(captor.capture());
204+
assertThat(captor.getValue()).isEqualTo("instrument-123_null");
205+
}
206+
207+
@Test
208+
@DisplayName("delete() id format should match getLastExecutionDate() id format")
209+
void delete_idFormatShouldMatchGetLastExecutionDate() throws GenesisException {
210+
//GIVEN
211+
// Ensure both methods build the id the same way
212+
LastJsonExtractionDocument doc = new LastJsonExtractionDocument();
213+
when(extractionRepository.findById(any())).thenReturn(Optional.of(doc));
214+
215+
//WHEN
216+
adapter.getLastExecutionDate(COLLECTION_INSTRUMENT_ID, MODE);
217+
adapter.delete(COLLECTION_INSTRUMENT_ID, MODE);
218+
219+
//THEN
220+
ArgumentCaptor<String> findCaptor = ArgumentCaptor.forClass(String.class);
221+
ArgumentCaptor<String> deleteCaptor = ArgumentCaptor.forClass(String.class);
222+
verify(extractionRepository).findById(findCaptor.capture());
223+
verify(extractionRepository).deleteById(deleteCaptor.capture());
224+
225+
assertThat(findCaptor.getValue()).isEqualTo(deleteCaptor.getValue());
226+
}
227+
228+
@Test
229+
@DisplayName("delete() should work for all known modes")
230+
void delete_shouldWorkForAllModes() {
231+
for (Mode mode : Mode.values()) {
232+
//GIVEN
233+
String expectedId = String.format("%s_%s", COLLECTION_INSTRUMENT_ID, mode);
234+
235+
//WHEN
236+
adapter.delete(COLLECTION_INSTRUMENT_ID, mode);
237+
238+
//THEN
239+
verify(extractionRepository).deleteById(expectedId);
240+
}
241+
}
242+
}
243+
244+
// -------------------------------------------------------------------------
245+
// Helpers
246+
// -------------------------------------------------------------------------
247+
248+
private LastJsonExtractionModel buildModel() {
249+
return LastJsonExtractionModel.builder()
250+
.collectionInstrumentId(COLLECTION_INSTRUMENT_ID)
251+
.mode(MODE)
252+
.build();
253+
}
254+
}

0 commit comments

Comments
 (0)