|
15 | 15 | */ |
16 | 16 | package com.hubsante.hub.service; |
17 | 17 |
|
| 18 | +import static org.assertj.core.api.Assertions.assertThat; |
18 | 19 | import static org.assertj.core.api.Assertions.assertThatThrownBy; |
| 20 | +import static org.junit.jupiter.params.provider.Arguments.arguments; |
19 | 21 | import static org.mockito.ArgumentMatchers.any; |
20 | 22 | import static org.mockito.ArgumentMatchers.anyString; |
21 | 23 | import static org.mockito.Mockito.*; |
|
26 | 28 | import com.hubsante.hub.exception.HubPersistenceException; |
27 | 29 | import com.hubsante.hub.model.PersistedMessage; |
28 | 30 | import com.hubsante.hub.repository.PersistedMessageRepository; |
29 | | -import com.hubsante.hub.utils.EdxlUtils; |
30 | 31 | import com.hubsante.model.EdxlHandler; |
| 32 | +import com.hubsante.model.cisu.resources.info.ResourcesInfoCisuWrapper; |
31 | 33 | import com.hubsante.model.edxl.ContentMessage; |
32 | 34 | import com.hubsante.model.edxl.EdxlMessage; |
| 35 | +import com.hubsante.model.resources.info.ResourcesInfoWrapper; |
| 36 | +import com.hubsante.model.resources.status.ResourcesStatusWrapper; |
33 | 37 | import java.util.Map; |
| 38 | +import java.util.stream.Stream; |
34 | 39 | import org.junit.jupiter.api.BeforeEach; |
35 | 40 | import org.junit.jupiter.api.DisplayName; |
36 | 41 | import org.junit.jupiter.api.Test; |
37 | 42 | import org.junit.jupiter.api.extension.ExtendWith; |
| 43 | +import org.junit.jupiter.params.ParameterizedTest; |
| 44 | +import org.junit.jupiter.params.provider.Arguments; |
| 45 | +import org.junit.jupiter.params.provider.MethodSource; |
| 46 | +import org.mockito.ArgumentCaptor; |
38 | 47 | import org.mockito.Mock; |
39 | | -import org.mockito.MockedStatic; |
40 | 48 | import org.mockito.junit.jupiter.MockitoExtension; |
41 | 49 |
|
42 | 50 | @ExtendWith(MockitoExtension.class) |
43 | 51 | public class MessagePersistenceServiceTest { |
44 | 52 |
|
| 53 | + private static final String DISTRIBUTION_ID = "fr.health.samuA_test-distribution-id"; |
| 54 | + private static final String SERIALIZED_EDXL = "{\"distributionID\":\"test\"}"; |
| 55 | + |
45 | 56 | @Mock private PersistedMessageRepository repository; |
46 | 57 | @Mock private EdxlHandler edxlHandler; |
47 | 58 | @Mock private ObjectMapper objectMapper; |
48 | | - @Mock private EdxlMessage edxlMessage; |
49 | | - @Mock private ContentMessage contentMessage; |
| 59 | + @Mock private HubConfiguration hubConfig; |
50 | 60 |
|
51 | 61 | private MessagePersistenceService service; |
52 | | - @Mock private HubConfiguration hubConfig; |
53 | 62 |
|
54 | 63 | @BeforeEach |
55 | 64 | void setUp() { |
56 | 65 | service = new MessagePersistenceService(repository, edxlHandler, objectMapper, hubConfig); |
57 | | - // These stubs are not used in all tests, so lenient |
58 | | - lenient().when(edxlMessage.getFirstContentMessage()).thenReturn(contentMessage); |
59 | | - lenient().when(edxlMessage.getDistributionID()).thenReturn("test-distribution-id"); |
60 | 66 | } |
61 | 67 |
|
62 | | - // ─── Nexsis vhost (18 → 15) ─────────────────────────────────────────────── |
63 | | - |
64 | | - @Test |
65 | | - @DisplayName("should persist ResourcesInfoCisuWrapper when vhost is 15-nexsis_vactive") |
66 | | - void shouldPersistResourcesInfoCisuWrapperFromNexsisVhost() throws Exception { |
67 | | - when(hubConfig.getVhost()).thenReturn("15-nexsis_vactive"); |
68 | | - try (MockedStatic<EdxlUtils> mockedEdxlUtils = mockStatic(EdxlUtils.class)) { |
69 | | - mockedEdxlUtils |
70 | | - .when(() -> EdxlUtils.getUseCaseFromMessage(any())) |
71 | | - .thenReturn("ResourcesInfoCisuWrapper"); |
72 | | - when(edxlHandler.serializeJsonEDXL(any())).thenReturn("{\"distributionID\":\"test\"}"); |
73 | | - when(objectMapper.readValue(anyString(), any(TypeReference.class))) |
74 | | - .thenReturn(Map.of()); |
75 | | - |
76 | | - service.persist(edxlMessage); |
77 | | - |
78 | | - verify(repository, times(1)).save(any(PersistedMessage.class)); |
79 | | - } |
80 | | - } |
81 | | - |
82 | | - // ─── Health vhost (15 → 18) ─────────────────────────────────────────────── |
83 | | - |
84 | | - @Test |
85 | | - @DisplayName("should persist ResourcesInfoWrapper when vhost is 15-15_v*") |
86 | | - void shouldPersistResourcesInfoWrapperFromHealthVhost() throws Exception { |
87 | | - when(hubConfig.getVhost()).thenReturn("15-15_v2.1"); |
88 | | - try (MockedStatic<EdxlUtils> mockedEdxlUtils = mockStatic(EdxlUtils.class)) { |
89 | | - mockedEdxlUtils |
90 | | - .when(() -> EdxlUtils.getUseCaseFromMessage(any())) |
91 | | - .thenReturn("ResourcesInfoWrapper"); |
92 | | - when(edxlHandler.serializeJsonEDXL(any())).thenReturn("{\"distributionID\":\"test\"}"); |
93 | | - when(objectMapper.readValue(anyString(), any(TypeReference.class))) |
94 | | - .thenReturn(Map.of()); |
95 | | - |
96 | | - service.persist(edxlMessage); |
97 | | - |
98 | | - verify(repository, times(1)).save(any(PersistedMessage.class)); |
99 | | - } |
| 68 | + static Stream<Arguments> persistedUseCases() { |
| 69 | + return Stream.of( |
| 70 | + arguments("15-nexsis_vactive", new ResourcesInfoCisuWrapper()), |
| 71 | + arguments("15-15_v2.1", new ResourcesInfoWrapper()), |
| 72 | + arguments("15-15_v1.5", new ResourcesStatusWrapper())); |
100 | 73 | } |
101 | 74 |
|
102 | | - @Test |
103 | | - @DisplayName("should persist ResourcesStatusWrapper when vhost is 15-15_v*") |
104 | | - void shouldPersistResourcesStatusWrapperFromHealthVhost() throws Exception { |
105 | | - when(hubConfig.getVhost()).thenReturn("15-15_v1.5"); |
106 | | - try (MockedStatic<EdxlUtils> mockedEdxlUtils = mockStatic(EdxlUtils.class)) { |
107 | | - mockedEdxlUtils |
108 | | - .when(() -> EdxlUtils.getUseCaseFromMessage(any())) |
109 | | - .thenReturn("ResourcesStatusWrapper"); |
110 | | - when(edxlHandler.serializeJsonEDXL(any())).thenReturn("{\"distributionID\":\"test\"}"); |
111 | | - when(objectMapper.readValue(anyString(), any(TypeReference.class))) |
112 | | - .thenReturn(Map.of()); |
113 | | - |
114 | | - service.persist(edxlMessage); |
115 | | - |
116 | | - verify(repository, times(1)).save(any(PersistedMessage.class)); |
117 | | - } |
| 75 | + @ParameterizedTest(name = "{1} on vhost {0}") |
| 76 | + @MethodSource("persistedUseCases") |
| 77 | + @DisplayName("should persist the message under its use case name") |
| 78 | + void shouldPersistAllowedUseCase(String vhost, ContentMessage content) throws Exception { |
| 79 | + when(hubConfig.getVhost()).thenReturn(vhost); |
| 80 | + when(edxlHandler.serializeJsonEDXL(any())).thenReturn(SERIALIZED_EDXL); |
| 81 | + when(objectMapper.readValue(anyString(), any(TypeReference.class))).thenReturn(Map.of()); |
| 82 | + |
| 83 | + service.persist(messageCarrying(content)); |
| 84 | + |
| 85 | + ArgumentCaptor<PersistedMessage> saved = ArgumentCaptor.forClass(PersistedMessage.class); |
| 86 | + verify(repository, times(1)).save(saved.capture()); |
| 87 | + assertThat(saved.getValue().getType()) |
| 88 | + .as("persisted use case") |
| 89 | + .isEqualTo(content.getClass().getSimpleName()); |
118 | 90 | } |
119 | 91 |
|
120 | | - // ─── Error resilience ───────────────────────────────────────────────────── |
121 | | - |
122 | 92 | @Test |
123 | 93 | @DisplayName("should throw when repository.save() fails") |
124 | 94 | void shouldThrowWhenRepositoryFails() throws Exception { |
125 | 95 | when(hubConfig.getVhost()).thenReturn("15-nexsis_v1.9"); |
126 | | - try (MockedStatic<EdxlUtils> mockedEdxlUtils = mockStatic(EdxlUtils.class)) { |
127 | | - mockedEdxlUtils |
128 | | - .when(() -> EdxlUtils.getUseCaseFromMessage(any())) |
129 | | - .thenReturn("ResourcesInfoCisuWrapper"); |
130 | | - when(edxlHandler.serializeJsonEDXL(any())).thenReturn("{\"distributionID\":\"test\"}"); |
131 | | - when(objectMapper.readValue(anyString(), any(TypeReference.class))) |
132 | | - .thenReturn(Map.of()); |
133 | | - doThrow(new RuntimeException("MongoDB unavailable")).when(repository).save(any()); |
134 | | - |
135 | | - assertThatThrownBy(() -> service.persist(edxlMessage)) |
136 | | - .isInstanceOf(HubPersistenceException.class) |
137 | | - .hasMessageContaining("MongoDB unavailable"); |
138 | | - |
139 | | - // save() was attempted but failed |
140 | | - verify(repository, times(1)).save(any()); |
141 | | - } |
| 96 | + when(edxlHandler.serializeJsonEDXL(any())).thenReturn(SERIALIZED_EDXL); |
| 97 | + when(objectMapper.readValue(anyString(), any(TypeReference.class))).thenReturn(Map.of()); |
| 98 | + doThrow(new RuntimeException("MongoDB unavailable")).when(repository).save(any()); |
| 99 | + |
| 100 | + assertThatThrownBy(() -> service.persist(messageCarrying(new ResourcesInfoCisuWrapper()))) |
| 101 | + .isInstanceOf(HubPersistenceException.class) |
| 102 | + .hasMessageContaining("MongoDB unavailable"); |
| 103 | + |
| 104 | + // save() was attempted but failed |
| 105 | + verify(repository, times(1)).save(any()); |
142 | 106 | } |
143 | 107 |
|
144 | 108 | @Test |
145 | 109 | @DisplayName("should throw when serialization fails - save is never attempted") |
146 | 110 | void shouldThrowWhenSerializationFails() throws Exception { |
147 | 111 | when(hubConfig.getVhost()).thenReturn("15-15_v2.1"); |
148 | | - try (MockedStatic<EdxlUtils> mockedEdxlUtils = mockStatic(EdxlUtils.class)) { |
149 | | - mockedEdxlUtils |
150 | | - .when(() -> EdxlUtils.getUseCaseFromMessage(any())) |
151 | | - .thenReturn("ResourcesInfoWrapper"); |
152 | | - when(edxlHandler.serializeJsonEDXL(any())) |
153 | | - .thenThrow(new RuntimeException("Serialization error")); |
154 | | - |
155 | | - assertThatThrownBy(() -> service.persist(edxlMessage)) |
156 | | - .isInstanceOf(HubPersistenceException.class) |
157 | | - .hasMessageContaining("Serialization error"); |
158 | | - |
159 | | - // save() was never called because serialization failed before reaching it |
160 | | - verify(repository, never()).save(any()); |
161 | | - } |
| 112 | + when(edxlHandler.serializeJsonEDXL(any())) |
| 113 | + .thenThrow(new RuntimeException("Serialization error")); |
| 114 | + |
| 115 | + assertThatThrownBy(() -> service.persist(messageCarrying(new ResourcesInfoWrapper()))) |
| 116 | + .isInstanceOf(HubPersistenceException.class) |
| 117 | + .hasMessageContaining("Serialization error"); |
| 118 | + |
| 119 | + // save() was never called because serialization failed before reaching it |
| 120 | + verify(repository, never()).save(any()); |
| 121 | + } |
| 122 | + |
| 123 | + private static EdxlMessage messageCarrying(ContentMessage content) { |
| 124 | + EdxlMessage edxlMessage = new EdxlMessage(); |
| 125 | + edxlMessage.setDistributionID(DISTRIBUTION_ID); |
| 126 | + edxlMessage.setContentFrom(content); |
| 127 | + return edxlMessage; |
162 | 128 | } |
163 | 129 | } |
0 commit comments