Refactoring - Version stable
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package dev.lions.unionflow.server.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
@@ -35,6 +36,10 @@ class MembreKeycloakSyncServiceTest {
|
||||
@RestClient
|
||||
UserServiceClient userServiceClient;
|
||||
|
||||
// =========================================================================
|
||||
// provisionKeycloakUser
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser échoue si le membre n'existe pas")
|
||||
void provisionKeycloakUser_failsIfMembreNotFound() {
|
||||
@@ -85,4 +90,504 @@ class MembreKeycloakSyncServiceTest {
|
||||
verify(membreRepository).persist(membre);
|
||||
verify(userServiceClient).sendVerificationEmail(eq(createdUser.getId()), eq("unionflow"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser lève IllegalStateException si un user Keycloak existe déjà avec cet email")
|
||||
void provisionKeycloakUser_failsIfKeycloakUserAlreadyExists() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setEmail("duplicate@unionflow.dev");
|
||||
membre.setNom("Dupont");
|
||||
membre.setPrenom("Pierre");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserDTO existingUser = new UserDTO();
|
||||
existingUser.setId(UUID.randomUUID().toString());
|
||||
existingUser.setEmail("duplicate@unionflow.dev");
|
||||
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(Collections.singletonList(existingUser));
|
||||
when(userServiceClient.searchUsers(any(UserSearchCriteriaDTO.class))).thenReturn(searchResult);
|
||||
|
||||
assertThatThrownBy(() -> syncService.provisionKeycloakUser(membreId))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.hasMessageContaining("duplicate@unionflow.dev");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser continue si la recherche Keycloak lève une exception non-ISE")
|
||||
void provisionKeycloakUser_continuesOnSearchException() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setEmail("search-fail@unionflow.dev");
|
||||
membre.setNom("Search");
|
||||
membre.setPrenom("Fail");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
// search throws a non-ISE exception
|
||||
when(userServiceClient.searchUsers(any())).thenThrow(new RuntimeException("Service unavailable"));
|
||||
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId(UUID.randomUUID().toString());
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
|
||||
// Should not throw — it logs warning and continues
|
||||
syncService.provisionKeycloakUser(membreId);
|
||||
|
||||
verify(userServiceClient).createUser(any(UserDTO.class), eq("unionflow"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser tolère un ID Keycloak invalide (non-UUID) dans la réponse")
|
||||
void provisionKeycloakUser_toleratesInvalidKeycloakId() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setEmail("invalid-id@unionflow.dev");
|
||||
membre.setNom("Invalid");
|
||||
membre.setPrenom("Id");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(Collections.emptyList());
|
||||
when(userServiceClient.searchUsers(any())).thenReturn(searchResult);
|
||||
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId("not-a-valid-uuid!!!"); // invalid UUID
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
|
||||
// Should not throw — logs warning and persists with null keycloakId
|
||||
syncService.provisionKeycloakUser(membreId);
|
||||
|
||||
verify(membreRepository).persist(membre);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser lève RuntimeException si la création Keycloak échoue")
|
||||
void provisionKeycloakUser_throwsRuntimeExceptionOnCreateFailure() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setEmail("create-fail@unionflow.dev");
|
||||
membre.setNom("Create");
|
||||
membre.setPrenom("Fail");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(Collections.emptyList());
|
||||
when(userServiceClient.searchUsers(any())).thenReturn(searchResult);
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString()))
|
||||
.thenThrow(new RuntimeException("Keycloak create failed"));
|
||||
|
||||
assertThatThrownBy(() -> syncService.provisionKeycloakUser(membreId))
|
||||
.isInstanceOf(RuntimeException.class)
|
||||
.hasMessageContaining("Impossible de créer le compte Keycloak");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser tolère l'échec d'envoi de l'email de vérification")
|
||||
void provisionKeycloakUser_toleratesVerificationEmailFailure() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setEmail("email-fail@unionflow.dev");
|
||||
membre.setNom("Email");
|
||||
membre.setPrenom("Fail");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(Collections.emptyList());
|
||||
when(userServiceClient.searchUsers(any())).thenReturn(searchResult);
|
||||
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId(UUID.randomUUID().toString());
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
doThrow(new RuntimeException("SMTP unavailable"))
|
||||
.when(userServiceClient).sendVerificationEmail(anyString(), anyString());
|
||||
|
||||
// Should not throw — email failure is non-blocking
|
||||
syncService.provisionKeycloakUser(membreId);
|
||||
|
||||
verify(membreRepository).persist(membre);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// syncMembreToKeycloak
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("syncMembreToKeycloak lève NotFoundException si le membre n'existe pas")
|
||||
void syncMembreToKeycloak_failsIfMembreNotFound() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.empty());
|
||||
|
||||
assertThatThrownBy(() -> syncService.syncMembreToKeycloak(membreId))
|
||||
.isInstanceOf(NotFoundException.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncMembreToKeycloak provisionne automatiquement si pas de compte Keycloak")
|
||||
void syncMembreToKeycloak_provisionesIfNoKeycloakAccount() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setEmail("no-kc@unionflow.dev");
|
||||
membre.setNom("No");
|
||||
membre.setPrenom("KC");
|
||||
// keycloakId == null → doit appeler provisionKeycloakUser
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(Collections.emptyList());
|
||||
when(userServiceClient.searchUsers(any())).thenReturn(searchResult);
|
||||
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId(UUID.randomUUID().toString());
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
|
||||
syncService.syncMembreToKeycloak(membreId);
|
||||
|
||||
// provisionKeycloakUser was invoked internally
|
||||
verify(userServiceClient).createUser(any(UserDTO.class), eq("unionflow"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncMembreToKeycloak met à jour le user Keycloak si le membre est déjà lié")
|
||||
void syncMembreToKeycloak_updatesExistingKeycloakUser() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
UUID keycloakId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setKeycloakId(keycloakId);
|
||||
membre.setEmail("sync@unionflow.dev");
|
||||
membre.setNom("Sync");
|
||||
membre.setPrenom("Test");
|
||||
membre.setActif(true);
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserDTO remoteUser = new UserDTO();
|
||||
remoteUser.setId(keycloakId.toString());
|
||||
remoteUser.setRealmName("unionflow");
|
||||
when(userServiceClient.getUserById(eq(keycloakId.toString()), eq("unionflow")))
|
||||
.thenReturn(remoteUser);
|
||||
|
||||
syncService.syncMembreToKeycloak(membreId);
|
||||
|
||||
verify(userServiceClient).updateUser(eq(keycloakId.toString()), any(UserDTO.class), eq("unionflow"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncMembreToKeycloak lève RuntimeException si l'appel getUserById échoue")
|
||||
void syncMembreToKeycloak_throwsRuntimeExceptionOnGetUserFailure() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
UUID keycloakId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setKeycloakId(keycloakId);
|
||||
membre.setEmail("get-fail@unionflow.dev");
|
||||
membre.setNom("Get");
|
||||
membre.setPrenom("Fail");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
when(userServiceClient.getUserById(anyString(), anyString()))
|
||||
.thenThrow(new RuntimeException("Keycloak unreachable"));
|
||||
|
||||
assertThatThrownBy(() -> syncService.syncMembreToKeycloak(membreId))
|
||||
.isInstanceOf(RuntimeException.class)
|
||||
.hasMessageContaining("Impossible de synchroniser le user Keycloak");
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncMembreToKeycloak utilise actif=true par défaut si membre.actif est null")
|
||||
void syncMembreToKeycloak_usesDefaultEnabledWhenActifIsNull() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
UUID keycloakId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setKeycloakId(keycloakId);
|
||||
membre.setEmail("null-actif@unionflow.dev");
|
||||
membre.setNom("Null");
|
||||
membre.setPrenom("Actif");
|
||||
membre.setActif(null); // null → defaults to true
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserDTO remoteUser = new UserDTO();
|
||||
remoteUser.setId(keycloakId.toString());
|
||||
remoteUser.setRealmName("unionflow");
|
||||
when(userServiceClient.getUserById(anyString(), anyString())).thenReturn(remoteUser);
|
||||
|
||||
syncService.syncMembreToKeycloak(membreId);
|
||||
|
||||
verify(userServiceClient).updateUser(anyString(), any(UserDTO.class), anyString());
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// syncKeycloakToMembre
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("syncKeycloakToMembre ne fait rien si aucun Membre n'est lié au user Keycloak")
|
||||
void syncKeycloakToMembre_doesNothingIfNoMembreMapped() {
|
||||
String keycloakUserId = UUID.randomUUID().toString();
|
||||
when(membreRepository.findByKeycloakUserId(keycloakUserId)).thenReturn(Optional.empty());
|
||||
|
||||
syncService.syncKeycloakToMembre(keycloakUserId, "unionflow");
|
||||
|
||||
verifyNoInteractions(userServiceClient);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncKeycloakToMembre met à jour le Membre avec les données Keycloak")
|
||||
void syncKeycloakToMembre_updatesMembreFromKeycloak() {
|
||||
String keycloakUserId = UUID.randomUUID().toString();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(UUID.randomUUID());
|
||||
membre.setEmail("old@unionflow.dev");
|
||||
membre.setNom("OldNom");
|
||||
membre.setPrenom("OldPrenom");
|
||||
|
||||
when(membreRepository.findByKeycloakUserId(keycloakUserId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserDTO keycloakUser = new UserDTO();
|
||||
keycloakUser.setId(keycloakUserId);
|
||||
keycloakUser.setPrenom("NewPrenom");
|
||||
keycloakUser.setNom("NewNom");
|
||||
keycloakUser.setEmail("new@unionflow.dev");
|
||||
keycloakUser.setEnabled(false);
|
||||
|
||||
when(userServiceClient.getUserById(eq(keycloakUserId), eq("unionflow"))).thenReturn(keycloakUser);
|
||||
|
||||
syncService.syncKeycloakToMembre(keycloakUserId, "unionflow");
|
||||
|
||||
assertThat(membre.getPrenom()).isEqualTo("NewPrenom");
|
||||
assertThat(membre.getNom()).isEqualTo("NewNom");
|
||||
assertThat(membre.getEmail()).isEqualTo("new@unionflow.dev");
|
||||
assertThat(membre.getActif()).isFalse();
|
||||
verify(membreRepository).persist(membre);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncKeycloakToMembre utilise DEFAULT_REALM si realm est null")
|
||||
void syncKeycloakToMembre_usesDefaultRealmWhenNull() {
|
||||
String keycloakUserId = UUID.randomUUID().toString();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(UUID.randomUUID());
|
||||
when(membreRepository.findByKeycloakUserId(keycloakUserId)).thenReturn(Optional.of(membre));
|
||||
|
||||
UserDTO keycloakUser = new UserDTO();
|
||||
keycloakUser.setId(keycloakUserId);
|
||||
keycloakUser.setPrenom("P");
|
||||
keycloakUser.setNom("N");
|
||||
keycloakUser.setEmail("e@e.com");
|
||||
keycloakUser.setEnabled(true);
|
||||
|
||||
when(userServiceClient.getUserById(eq(keycloakUserId), eq("unionflow"))).thenReturn(keycloakUser);
|
||||
|
||||
syncService.syncKeycloakToMembre(keycloakUserId, null); // null realm
|
||||
|
||||
verify(userServiceClient).getUserById(eq(keycloakUserId), eq("unionflow"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("syncKeycloakToMembre lève RuntimeException si getUserById échoue")
|
||||
void syncKeycloakToMembre_throwsRuntimeExceptionOnFailure() {
|
||||
String keycloakUserId = UUID.randomUUID().toString();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(UUID.randomUUID());
|
||||
when(membreRepository.findByKeycloakUserId(keycloakUserId)).thenReturn(Optional.of(membre));
|
||||
when(userServiceClient.getUserById(anyString(), anyString()))
|
||||
.thenThrow(new RuntimeException("Timeout"));
|
||||
|
||||
assertThatThrownBy(() -> syncService.syncKeycloakToMembre(keycloakUserId, "unionflow"))
|
||||
.isInstanceOf(RuntimeException.class)
|
||||
.hasMessageContaining("Impossible de synchroniser depuis Keycloak");
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// findMembreByKeycloakUserId
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("findMembreByKeycloakUserId retourne Optional.empty() si aucun membre n'est lié")
|
||||
void findMembreByKeycloakUserId_returnsEmptyIfNotFound() {
|
||||
String keycloakUserId = UUID.randomUUID().toString();
|
||||
when(membreRepository.findByKeycloakUserId(keycloakUserId)).thenReturn(Optional.empty());
|
||||
|
||||
Optional<Membre> result = syncService.findMembreByKeycloakUserId(keycloakUserId);
|
||||
|
||||
assertThat(result).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("findMembreByKeycloakUserId retourne le Membre lié si trouvé")
|
||||
void findMembreByKeycloakUserId_returnsMembre() {
|
||||
String keycloakUserId = UUID.randomUUID().toString();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(UUID.randomUUID());
|
||||
membre.setEmail("linked@unionflow.dev");
|
||||
|
||||
when(membreRepository.findByKeycloakUserId(keycloakUserId)).thenReturn(Optional.of(membre));
|
||||
|
||||
Optional<Membre> result = syncService.findMembreByKeycloakUserId(keycloakUserId);
|
||||
|
||||
assertThat(result).isPresent();
|
||||
assertThat(result.get()).isSameAs(membre);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// unlinkKeycloakUser
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("unlinkKeycloakUser lève NotFoundException si le membre n'existe pas")
|
||||
void unlinkKeycloakUser_failsIfMembreNotFound() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.empty());
|
||||
|
||||
assertThatThrownBy(() -> syncService.unlinkKeycloakUser(membreId))
|
||||
.isInstanceOf(NotFoundException.class);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// provisionKeycloakUser — branche searchResult == null (L97 branche null)
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser avec searchResult==null depuis API → continue (branche null L97)")
|
||||
void provisionKeycloakUser_searchResultNull_continues() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setNom("Null");
|
||||
membre.setPrenom("Search");
|
||||
membre.setEmail("null-search-" + membreId + "@test.com");
|
||||
membre.setKeycloakId(null);
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
// searchResult == null → condition L97 = false → continue
|
||||
when(userServiceClient.searchUsers(any(UserSearchCriteriaDTO.class))).thenReturn(null);
|
||||
// provisionKeycloakUser tente ensuite de créer l'utilisateur via createUser
|
||||
// On mock createUser pour qu'il retourne un UserDTO valide
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId(UUID.randomUUID().toString());
|
||||
createdUser.setUsername(membre.getEmail());
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
|
||||
// Ne doit pas lever d'exception (searchResult null → condition false → continue)
|
||||
org.assertj.core.api.Assertions.assertThatCode(() -> syncService.provisionKeycloakUser(membreId))
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser avec searchResult.getUsers()==null → continue (branche getUsers()==null L97)")
|
||||
void provisionKeycloakUser_usersNull_continues() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setNom("UsersNull");
|
||||
membre.setPrenom("Test");
|
||||
membre.setEmail("users-null-" + membreId + "@test.com");
|
||||
membre.setKeycloakId(null);
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
// searchResult non-null mais users == null → condition L97 = false → continue
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(null);
|
||||
when(userServiceClient.searchUsers(any(UserSearchCriteriaDTO.class))).thenReturn(searchResult);
|
||||
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId(UUID.randomUUID().toString());
|
||||
createdUser.setUsername(membre.getEmail());
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
|
||||
org.assertj.core.api.Assertions.assertThatCode(() -> syncService.provisionKeycloakUser(membreId))
|
||||
.doesNotThrowAnyException();
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// L117: createdUser.getId() == null → false branch (skip setKeycloakId)
|
||||
// =========================================================================
|
||||
|
||||
@Test
|
||||
@DisplayName("provisionKeycloakUser avec createdUser.getId() null → L117 false → keycloakId non settée")
|
||||
void provisionKeycloakUser_createdUserIdNull_L117False_keycloakIdNotSet() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setNom("IdNull");
|
||||
membre.setPrenom("Test");
|
||||
membre.setEmail("id-null-" + membreId + "@test.com");
|
||||
membre.setKeycloakId(null);
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
// searchResult null ou sans users → membre not found → create
|
||||
UserSearchResultDTO searchResult = new UserSearchResultDTO();
|
||||
searchResult.setUsers(null);
|
||||
when(userServiceClient.searchUsers(any(UserSearchCriteriaDTO.class))).thenReturn(searchResult);
|
||||
|
||||
// createdUser with getId() = null → L117: null != null = false → skip setKeycloakId
|
||||
UserDTO createdUser = new UserDTO();
|
||||
createdUser.setId(null); // null → L117 false branch
|
||||
when(userServiceClient.createUser(any(UserDTO.class), anyString())).thenReturn(createdUser);
|
||||
|
||||
org.assertj.core.api.Assertions.assertThatCode(() -> syncService.provisionKeycloakUser(membreId))
|
||||
.doesNotThrowAnyException();
|
||||
|
||||
// keycloakId should remain null since getId() was null
|
||||
assertThat(membre.getKeycloakId()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("unlinkKeycloakUser ne fait rien si le membre n'a pas de compte Keycloak lié")
|
||||
void unlinkKeycloakUser_doesNothingIfNoKeycloakId() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setKeycloakId(null);
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
syncService.unlinkKeycloakUser(membreId);
|
||||
|
||||
// persist should not be called when there is nothing to unlink
|
||||
verify(membreRepository, never()).persist(any(Membre.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("unlinkKeycloakUser supprime le lien Keycloak et persiste le membre")
|
||||
void unlinkKeycloakUser_removesKeycloakLink() {
|
||||
UUID membreId = UUID.randomUUID();
|
||||
UUID keycloakId = UUID.randomUUID();
|
||||
|
||||
Membre membre = new Membre();
|
||||
membre.setId(membreId);
|
||||
membre.setKeycloakId(keycloakId);
|
||||
membre.setNom("Unlink");
|
||||
membre.setPrenom("Test");
|
||||
|
||||
when(membreRepository.findByIdOptional(membreId)).thenReturn(Optional.of(membre));
|
||||
|
||||
syncService.unlinkKeycloakUser(membreId);
|
||||
|
||||
assertThat(membre.getKeycloakId()).isNull();
|
||||
verify(membreRepository).persist(membre);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user