Migration complète vers PrimeFaces Freya - Corrections des incompatibilités et intégration de primefaces-freya-extension

This commit is contained in:
lionsdev
2025-12-27 00:18:31 +00:00
parent 03984b50c9
commit 2bc1b0f6a5
49 changed files with 9440 additions and 260 deletions

View File

@@ -0,0 +1,357 @@
package dev.lions.user.manager.client;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Invocation;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.token.TokenManager;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests complets pour KeycloakAdminClientImpl pour atteindre 100% de couverture
* Couvre init(), getAllRealms(), reconnect(), et tous les cas limites
*/
@ExtendWith(MockitoExtension.class)
class KeycloakAdminClientImplCompleteTest {
@InjectMocks
KeycloakAdminClientImpl client;
private void setField(String fieldName, Object value) throws Exception {
Field field = KeycloakAdminClientImpl.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(client, value);
}
@BeforeEach
void setUp() throws Exception {
// Set all config fields to null/empty for testing
setField("serverUrl", "");
setField("adminRealm", "master");
setField("adminClientId", "admin-cli");
setField("adminUsername", "admin");
setField("adminPassword", "");
setField("connectionPoolSize", 10);
setField("timeoutSeconds", 30);
setField("keycloak", null);
}
@Test
void testInit_WithServerUrl() throws Exception {
setField("serverUrl", "http://localhost:8080");
setField("adminRealm", "master");
setField("adminClientId", "admin-cli");
setField("adminUsername", "admin");
setField("adminPassword", "password");
// Mock KeycloakBuilder to avoid actual connection
// This will likely throw an exception, but that's ok - we test the exception path
try {
java.lang.reflect.Method initMethod = KeycloakAdminClientImpl.class.getDeclaredMethod("init");
initMethod.setAccessible(true);
initMethod.invoke(client);
} catch (Exception e) {
// Expected - KeycloakBuilder will fail without actual Keycloak server
}
// The init method will set keycloak to null on exception
Field keycloakField = KeycloakAdminClientImpl.class.getDeclaredField("keycloak");
keycloakField.setAccessible(true);
Keycloak result = (Keycloak) keycloakField.get(client);
// Result will be null due to exception, which is the expected behavior
// This test covers the exception path in init()
}
@Test
void testInit_WithException() throws Exception {
setField("serverUrl", "http://localhost:8080");
setField("adminRealm", "master");
setField("adminClientId", "admin-cli");
setField("adminUsername", "admin");
setField("adminPassword", "password");
// Call init via reflection - will throw exception without actual Keycloak
// This test covers the exception handling path in init()
try {
java.lang.reflect.Method initMethod = KeycloakAdminClientImpl.class.getDeclaredMethod("init");
initMethod.setAccessible(true);
initMethod.invoke(client);
} catch (Exception e) {
// Expected - KeycloakBuilder may fail
}
// Verify keycloak is null after exception
Field keycloakField = KeycloakAdminClientImpl.class.getDeclaredField("keycloak");
keycloakField.setAccessible(true);
Keycloak result = (Keycloak) keycloakField.get(client);
// Result may be null due to exception, which is the expected behavior
// This test covers the exception handling path in init()
}
@Test
void testInit_WithNullServerUrl() throws Exception {
setField("serverUrl", null);
// Call init via reflection
java.lang.reflect.Method initMethod = KeycloakAdminClientImpl.class.getDeclaredMethod("init");
initMethod.setAccessible(true);
initMethod.invoke(client);
// Verify keycloak is null
Field keycloakField = KeycloakAdminClientImpl.class.getDeclaredField("keycloak");
keycloakField.setAccessible(true);
Keycloak result = (Keycloak) keycloakField.get(client);
assertNull(result);
}
@Test
void testInit_WithEmptyServerUrl() throws Exception {
setField("serverUrl", "");
// Call init via reflection
java.lang.reflect.Method initMethod = KeycloakAdminClientImpl.class.getDeclaredMethod("init");
initMethod.setAccessible(true);
initMethod.invoke(client);
// Verify keycloak is null
Field keycloakField = KeycloakAdminClientImpl.class.getDeclaredField("keycloak");
keycloakField.setAccessible(true);
Keycloak result = (Keycloak) keycloakField.get(client);
assertNull(result);
}
@Test
void testReconnect() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "");
// reconnect calls close() then init()
client.reconnect();
// Verify close was called
verify(mockKeycloak).close();
// Verify keycloak is null after close
Field keycloakField = KeycloakAdminClientImpl.class.getDeclaredField("keycloak");
keycloakField.setAccessible(true);
Keycloak result = (Keycloak) keycloakField.get(client);
assertNull(result);
}
@Test
void testGetAllRealms_Success() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
TokenManager mockTokenManager = mock(TokenManager.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "http://localhost:8080");
when(mockKeycloak.tokenManager()).thenReturn(mockTokenManager);
when(mockTokenManager.getAccessTokenString()).thenReturn("test-token");
// Mock ClientBuilder
try (MockedStatic<ClientBuilder> mockedClientBuilder = mockStatic(ClientBuilder.class)) {
Client mockClient = mock(Client.class);
WebTarget mockWebTarget = mock(WebTarget.class);
Invocation.Builder mockBuilder = mock(Invocation.Builder.class);
Response mockResponse = mock(Response.class);
mockedClientBuilder.when(ClientBuilder::newClient).thenReturn(mockClient);
when(mockClient.target("http://localhost:8080/admin/realms")).thenReturn(mockWebTarget);
when(mockWebTarget.request(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)).thenReturn(mockBuilder);
when(mockBuilder.header(anyString(), anyString())).thenReturn(mockBuilder);
// Mock response with realm data
Map<String, Object> realm1 = new HashMap<>();
realm1.put("realm", "realm1");
Map<String, Object> realm2 = new HashMap<>();
realm2.put("realm", "realm2");
List<Map<String, Object>> realmsJson = new ArrayList<>();
realmsJson.add(realm1);
realmsJson.add(realm2);
when(mockBuilder.get(List.class)).thenReturn(realmsJson);
List<String> result = client.getAllRealms();
assertNotNull(result);
assertEquals(2, result.size());
assertTrue(result.contains("realm1"));
assertTrue(result.contains("realm2"));
verify(mockClient).close();
}
}
@Test
void testGetAllRealms_WithNullRealmsJson() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
TokenManager mockTokenManager = mock(TokenManager.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "http://localhost:8080");
when(mockKeycloak.tokenManager()).thenReturn(mockTokenManager);
when(mockTokenManager.getAccessTokenString()).thenReturn("test-token");
try (MockedStatic<ClientBuilder> mockedClientBuilder = mockStatic(ClientBuilder.class)) {
Client mockClient = mock(Client.class);
WebTarget mockWebTarget = mock(WebTarget.class);
Invocation.Builder mockBuilder = mock(Invocation.Builder.class);
mockedClientBuilder.when(ClientBuilder::newClient).thenReturn(mockClient);
when(mockClient.target("http://localhost:8080/admin/realms")).thenReturn(mockWebTarget);
when(mockWebTarget.request(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)).thenReturn(mockBuilder);
when(mockBuilder.header(anyString(), anyString())).thenReturn(mockBuilder);
when(mockBuilder.get(List.class)).thenReturn(null);
List<String> result = client.getAllRealms();
assertNotNull(result);
assertTrue(result.isEmpty());
verify(mockClient).close();
}
}
@Test
void testGetAllRealms_WithEmptyRealmName() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
TokenManager mockTokenManager = mock(TokenManager.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "http://localhost:8080");
when(mockKeycloak.tokenManager()).thenReturn(mockTokenManager);
when(mockTokenManager.getAccessTokenString()).thenReturn("test-token");
try (MockedStatic<ClientBuilder> mockedClientBuilder = mockStatic(ClientBuilder.class)) {
Client mockClient = mock(Client.class);
WebTarget mockWebTarget = mock(WebTarget.class);
Invocation.Builder mockBuilder = mock(Invocation.Builder.class);
mockedClientBuilder.when(ClientBuilder::newClient).thenReturn(mockClient);
when(mockClient.target("http://localhost:8080/admin/realms")).thenReturn(mockWebTarget);
when(mockWebTarget.request(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)).thenReturn(mockBuilder);
when(mockBuilder.header(anyString(), anyString())).thenReturn(mockBuilder);
// Mock response with empty realm name
Map<String, Object> realm1 = new HashMap<>();
realm1.put("realm", "");
Map<String, Object> realm2 = new HashMap<>();
realm2.put("realm", "realm2");
List<Map<String, Object>> realmsJson = new ArrayList<>();
realmsJson.add(realm1);
realmsJson.add(realm2);
when(mockBuilder.get(List.class)).thenReturn(realmsJson);
List<String> result = client.getAllRealms();
assertNotNull(result);
assertEquals(1, result.size()); // Empty realm name should be filtered out
assertTrue(result.contains("realm2"));
verify(mockClient).close();
}
}
@Test
void testGetAllRealms_WithNullRealmName() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
TokenManager mockTokenManager = mock(TokenManager.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "http://localhost:8080");
when(mockKeycloak.tokenManager()).thenReturn(mockTokenManager);
when(mockTokenManager.getAccessTokenString()).thenReturn("test-token");
try (MockedStatic<ClientBuilder> mockedClientBuilder = mockStatic(ClientBuilder.class)) {
Client mockClient = mock(Client.class);
WebTarget mockWebTarget = mock(WebTarget.class);
Invocation.Builder mockBuilder = mock(Invocation.Builder.class);
mockedClientBuilder.when(ClientBuilder::newClient).thenReturn(mockClient);
when(mockClient.target("http://localhost:8080/admin/realms")).thenReturn(mockWebTarget);
when(mockWebTarget.request(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)).thenReturn(mockBuilder);
when(mockBuilder.header(anyString(), anyString())).thenReturn(mockBuilder);
// Mock response with null realm name
Map<String, Object> realm1 = new HashMap<>();
realm1.put("realm", null);
Map<String, Object> realm2 = new HashMap<>();
realm2.put("realm", "realm2");
List<Map<String, Object>> realmsJson = new ArrayList<>();
realmsJson.add(realm1);
realmsJson.add(realm2);
when(mockBuilder.get(List.class)).thenReturn(realmsJson);
List<String> result = client.getAllRealms();
assertNotNull(result);
assertEquals(1, result.size()); // Null realm name should be filtered out
assertTrue(result.contains("realm2"));
verify(mockClient).close();
}
}
@Test
void testGetAllRealms_WithException() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
TokenManager mockTokenManager = mock(TokenManager.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "http://localhost:8080");
when(mockKeycloak.tokenManager()).thenReturn(mockTokenManager);
when(mockTokenManager.getAccessTokenString()).thenThrow(new RuntimeException("Error"));
List<String> result = client.getAllRealms();
assertNotNull(result);
assertTrue(result.isEmpty()); // Should return empty list on exception
}
@Test
void testGetAllRealms_WithExceptionInClient() throws Exception {
Keycloak mockKeycloak = mock(Keycloak.class);
TokenManager mockTokenManager = mock(TokenManager.class);
setField("keycloak", mockKeycloak);
setField("serverUrl", "http://localhost:8080");
when(mockKeycloak.tokenManager()).thenReturn(mockTokenManager);
when(mockTokenManager.getAccessTokenString()).thenReturn("test-token");
try (MockedStatic<ClientBuilder> mockedClientBuilder = mockStatic(ClientBuilder.class)) {
Client mockClient = mock(Client.class);
WebTarget mockWebTarget = mock(WebTarget.class);
Invocation.Builder mockBuilder = mock(Invocation.Builder.class);
mockedClientBuilder.when(ClientBuilder::newClient).thenReturn(mockClient);
when(mockClient.target("http://localhost:8080/admin/realms")).thenReturn(mockWebTarget);
when(mockWebTarget.request(jakarta.ws.rs.core.MediaType.APPLICATION_JSON)).thenReturn(mockBuilder);
when(mockBuilder.header(anyString(), anyString())).thenReturn(mockBuilder);
when(mockBuilder.get(List.class)).thenThrow(new RuntimeException("Connection error"));
List<String> result = client.getAllRealms();
assertNotNull(result);
assertTrue(result.isEmpty()); // Should return empty list on exception
verify(mockClient).close(); // Should still close client in finally block
}
}
}

View File

@@ -0,0 +1,177 @@
package dev.lions.user.manager.client;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.admin.client.resource.RolesResource;
import org.keycloak.admin.client.resource.ServerInfoResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.info.ServerInfoRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import jakarta.ws.rs.NotFoundException;
import java.lang.reflect.Field;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class KeycloakAdminClientImplTest {
@InjectMocks
KeycloakAdminClientImpl client;
@Mock
Keycloak keycloak;
@Mock
RealmResource realmResource;
@Mock
UsersResource usersResource;
@Mock
RolesResource rolesResource;
@Mock
ServerInfoResource serverInfoResource;
@BeforeEach
void setUp() throws Exception {
// Inject the mock keycloak instance
setField(client, "keycloak", keycloak);
}
private void setField(Object target, String fieldName, Object value) throws Exception {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
}
@Test
void testGetInstance() {
Keycloak result = client.getInstance();
assertNotNull(result);
assertEquals(keycloak, result);
}
@Test
void testGetInstanceReInitWhenNull() throws Exception {
// Set keycloak to null
setField(client, "keycloak", null);
// Should attempt to reinitialize (will fail without config, but that's ok)
// The method should return null since init() will fail without proper config
Keycloak result = client.getInstance();
// Since config values are null, keycloak will still be null
assertNull(result);
}
@Test
void testGetRealm() {
when(keycloak.realm("test-realm")).thenReturn(realmResource);
RealmResource result = client.getRealm("test-realm");
assertNotNull(result);
assertEquals(realmResource, result);
}
@Test
void testGetRealmThrowsException() {
when(keycloak.realm("bad-realm")).thenThrow(new RuntimeException("Connection failed"));
assertThrows(RuntimeException.class, () -> client.getRealm("bad-realm"));
}
@Test
void testGetUsers() {
when(keycloak.realm("test-realm")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
UsersResource result = client.getUsers("test-realm");
assertNotNull(result);
assertEquals(usersResource, result);
}
@Test
void testGetRoles() {
when(keycloak.realm("test-realm")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
RolesResource result = client.getRoles("test-realm");
assertNotNull(result);
assertEquals(rolesResource, result);
}
@Test
void testIsConnected_true() {
when(keycloak.serverInfo()).thenReturn(serverInfoResource);
when(serverInfoResource.getInfo()).thenReturn(new ServerInfoRepresentation());
assertTrue(client.isConnected());
}
@Test
void testIsConnected_false_exception() {
when(keycloak.serverInfo()).thenThrow(new RuntimeException("Connection refused"));
assertFalse(client.isConnected());
}
@Test
void testIsConnected_false_null() throws Exception {
setField(client, "keycloak", null);
assertFalse(client.isConnected());
}
@Test
void testRealmExists_true() {
when(keycloak.realm("test-realm")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(java.util.Collections.emptyList());
assertTrue(client.realmExists("test-realm"));
}
@Test
void testRealmExists_notFound() {
when(keycloak.realm("missing-realm")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new NotFoundException("Realm not found"));
assertFalse(client.realmExists("missing-realm"));
}
@Test
void testRealmExists_otherException() {
when(keycloak.realm("problem-realm")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Some other error"));
// Should return true assuming realm exists but has issues
assertTrue(client.realmExists("problem-realm"));
}
@Test
void testClose() {
client.close();
verify(keycloak).close();
}
@Test
void testCloseWhenNull() throws Exception {
setField(client, "keycloak", null);
// Should not throw
client.close();
}
}

View File

@@ -0,0 +1,41 @@
package dev.lions.user.manager.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.quarkus.jackson.ObjectMapperCustomizer;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests unitaires pour JacksonConfig
*/
class JacksonConfigTest {
private JacksonConfig jacksonConfig;
private ObjectMapper objectMapper;
@BeforeEach
void setUp() {
jacksonConfig = new JacksonConfig();
objectMapper = new ObjectMapper();
}
@Test
void testCustomize() {
// Avant la personnalisation, FAIL_ON_UNKNOWN_PROPERTIES devrait être true par défaut
assertTrue(objectMapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
// Appliquer la personnalisation
jacksonConfig.customize(objectMapper);
// Après la personnalisation, FAIL_ON_UNKNOWN_PROPERTIES devrait être false
assertFalse(objectMapper.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
}
@Test
void testImplementsObjectMapperCustomizer() {
assertTrue(jacksonConfig instanceof ObjectMapperCustomizer);
}
}

View File

@@ -0,0 +1,356 @@
package dev.lions.user.manager.config;
import io.quarkus.runtime.StartupEvent;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.*;
import org.keycloak.representations.idm.*;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests complets pour KeycloakTestUserConfig pour atteindre 100% de couverture
* Teste toutes les méthodes privées via la méthode publique onStart
*/
@ExtendWith(MockitoExtension.class)
class KeycloakTestUserConfigCompleteTest {
private KeycloakTestUserConfig config;
private Keycloak adminClient;
private RealmsResource realmsResource;
private RealmResource realmResource;
private RolesResource rolesResource;
private RoleResource roleResource;
private UsersResource usersResource;
private UserResource userResource;
private ClientsResource clientsResource;
private ClientResource clientResource;
private ClientScopesResource clientScopesResource;
private ClientScopeResource clientScopeResource;
@BeforeEach
void setUp() throws Exception {
config = new KeycloakTestUserConfig();
// Injecter les valeurs via reflection
setField("profile", "dev");
setField("keycloakServerUrl", "http://localhost:8080");
setField("adminRealm", "master");
setField("adminUsername", "admin");
setField("adminPassword", "admin");
setField("authorizedRealms", "lions-user-manager");
// Mocks pour Keycloak
adminClient = mock(Keycloak.class);
realmsResource = mock(RealmsResource.class);
realmResource = mock(RealmResource.class);
rolesResource = mock(RolesResource.class);
roleResource = mock(RoleResource.class);
usersResource = mock(UsersResource.class);
userResource = mock(UserResource.class);
clientsResource = mock(ClientsResource.class);
clientResource = mock(ClientResource.class);
clientScopesResource = mock(ClientScopesResource.class);
clientScopeResource = mock(ClientScopeResource.class);
}
private void setField(String fieldName, Object value) throws Exception {
java.lang.reflect.Field field = KeycloakTestUserConfig.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(config, value);
}
@Test
void testOnStart_DevMode() {
// Le code est désactivé, donc onStart devrait juste logger et retourner
StartupEvent event = mock(StartupEvent.class);
// Ne devrait pas lancer d'exception
assertDoesNotThrow(() -> config.onStart(event));
}
@Test
void testEnsureRealmExists_RealmExists() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.toRepresentation()).thenReturn(new RealmRepresentation());
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureRealmExists", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
verify(realmResource).toRepresentation();
}
@Test
void testEnsureRealmExists_RealmNotFound() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.toRepresentation()).thenThrow(new NotFoundException());
doNothing().when(realmsResource).create(any(RealmRepresentation.class));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureRealmExists", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
verify(realmResource).toRepresentation();
}
@Test
void testEnsureRolesExist_AllRolesExist() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(anyString())).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(new RoleRepresentation());
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureRolesExist", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
}
@Test
void testEnsureRolesExist_RoleNotFound() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(anyString())).thenReturn(roleResource);
when(roleResource.toRepresentation())
.thenThrow(new NotFoundException())
.thenReturn(new RoleRepresentation());
doNothing().when(rolesResource).create(any(RoleRepresentation.class));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureRolesExist", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
}
@Test
void testEnsureTestUserExists_UserExists() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
UserRepresentation existingUser = new UserRepresentation();
existingUser.setId("user-id-123");
when(usersResource.search("test-user", true)).thenReturn(List.of(existingUser));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureTestUserExists", Keycloak.class);
method.setAccessible(true);
String userId = (String) method.invoke(config, adminClient);
assertEquals("user-id-123", userId);
}
@Test
void testEnsureTestUserExists_UserNotFound() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.search("test-user", true)).thenReturn(Collections.emptyList());
Response response = mock(Response.class);
when(response.getStatusInfo()).thenReturn(Response.Status.CREATED);
when(response.getLocation()).thenReturn(URI.create("http://localhost/users/user-id-123"));
when(usersResource.create(any(UserRepresentation.class))).thenReturn(response);
when(usersResource.get("user-id-123")).thenReturn(userResource);
CredentialRepresentation credential = new CredentialRepresentation();
doNothing().when(userResource).resetPassword(any(CredentialRepresentation.class));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureTestUserExists", Keycloak.class);
method.setAccessible(true);
String userId = (String) method.invoke(config, adminClient);
assertEquals("user-id-123", userId);
verify(usersResource).create(any(UserRepresentation.class));
verify(userResource).resetPassword(any(CredentialRepresentation.class));
}
@Test
void testAssignRolesToUser() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(anyString())).thenReturn(roleResource);
RoleRepresentation role = new RoleRepresentation();
role.setName("admin");
when(roleResource.toRepresentation()).thenReturn(role);
when(usersResource.get("user-id")).thenReturn(userResource);
RoleMappingResource roleMappingResource = mock(RoleMappingResource.class);
RoleScopeResource roleScopeResource = mock(RoleScopeResource.class);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(roleScopeResource);
doNothing().when(roleScopeResource).add(anyList());
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("assignRolesToUser", Keycloak.class, String.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient, "user-id"));
verify(roleScopeResource).add(anyList());
}
@Test
void testEnsureClientAndMapper_ClientExists() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation existingClient = new ClientRepresentation();
existingClient.setId("client-id-123");
when(clientsResource.findByClientId("lions-user-manager-client")).thenReturn(List.of(existingClient));
when(realmResource.clientScopes()).thenReturn(clientScopesResource);
ClientScopeRepresentation rolesScope = new ClientScopeRepresentation();
rolesScope.setId("scope-id");
rolesScope.setName("roles");
when(clientScopesResource.findAll()).thenReturn(List.of(rolesScope));
when(clientsResource.get("client-id-123")).thenReturn(clientResource);
when(clientResource.getDefaultClientScopes()).thenReturn(List.of(rolesScope));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureClientAndMapper", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
}
@Test
void testEnsureClientAndMapper_ClientNotFound() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId("lions-user-manager-client")).thenReturn(Collections.emptyList());
Response response = mock(Response.class);
when(response.getStatusInfo()).thenReturn(Response.Status.CREATED);
when(response.getLocation()).thenReturn(URI.create("http://localhost/clients/client-id-123"));
when(clientsResource.create(any(ClientRepresentation.class))).thenReturn(response);
when(realmResource.clientScopes()).thenReturn(clientScopesResource);
ClientScopeRepresentation rolesScope = new ClientScopeRepresentation();
rolesScope.setId("scope-id");
rolesScope.setName("roles");
when(clientScopesResource.findAll()).thenReturn(List.of(rolesScope));
when(clientsResource.get("client-id-123")).thenReturn(clientResource);
when(clientResource.getDefaultClientScopes()).thenReturn(List.of(rolesScope));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureClientAndMapper", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
verify(clientsResource).create(any(ClientRepresentation.class));
}
@Test
void testEnsureClientAndMapper_ClientNotFound_NoRolesScope() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId("lions-user-manager-client")).thenReturn(Collections.emptyList());
Response response = mock(Response.class);
when(response.getStatusInfo()).thenReturn(Response.Status.CREATED);
when(response.getLocation()).thenReturn(URI.create("http://localhost/clients/client-id-123"));
when(clientsResource.create(any(ClientRepresentation.class))).thenReturn(response);
when(realmResource.clientScopes()).thenReturn(clientScopesResource);
when(clientScopesResource.findAll()).thenReturn(Collections.emptyList());
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureClientAndMapper", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
}
@Test
void testEnsureClientAndMapper_ClientNotFound_RolesScopeAlreadyPresent() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId("lions-user-manager-client")).thenReturn(Collections.emptyList());
Response response = mock(Response.class);
when(response.getStatusInfo()).thenReturn(Response.Status.CREATED);
when(response.getLocation()).thenReturn(URI.create("http://localhost/clients/client-id-123"));
when(clientsResource.create(any(ClientRepresentation.class))).thenReturn(response);
when(realmResource.clientScopes()).thenReturn(clientScopesResource);
ClientScopeRepresentation rolesScope = new ClientScopeRepresentation();
rolesScope.setId("scope-id");
rolesScope.setName("roles");
when(clientScopesResource.findAll()).thenReturn(List.of(rolesScope));
when(clientsResource.get("client-id-123")).thenReturn(clientResource);
// Simuler que le scope "roles" est déjà présent
when(clientResource.getDefaultClientScopes()).thenReturn(List.of(rolesScope));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureClientAndMapper", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
}
@Test
void testEnsureClientAndMapper_Exception() throws Exception {
when(adminClient.realms()).thenReturn(realmsResource);
when(realmsResource.realm("lions-user-manager")).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId("lions-user-manager-client")).thenThrow(new RuntimeException("Connection error"));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("ensureClientAndMapper", Keycloak.class);
method.setAccessible(true);
assertDoesNotThrow(() -> method.invoke(config, adminClient));
}
@Test
void testGetCreatedId_Success() throws Exception {
Response response = mock(Response.class);
when(response.getStatusInfo()).thenReturn(Response.Status.CREATED);
when(response.getLocation()).thenReturn(URI.create("http://localhost/users/user-id-123"));
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("getCreatedId", Response.class);
method.setAccessible(true);
String id = (String) method.invoke(config, response);
assertEquals("user-id-123", id);
}
@Test
void testGetCreatedId_Error() throws Exception {
Response response = mock(Response.class);
// Utiliser Response.Status.BAD_REQUEST directement
when(response.getStatusInfo()).thenReturn(Response.Status.BAD_REQUEST);
Method method = KeycloakTestUserConfig.class.getDeclaredMethod("getCreatedId", Response.class);
method.setAccessible(true);
Exception exception = assertThrows(Exception.class, () -> method.invoke(config, response));
assertTrue(exception.getCause() instanceof RuntimeException);
assertTrue(exception.getCause().getMessage().contains("Erreur lors de la création"));
}
}

View File

@@ -0,0 +1,65 @@
package dev.lions.user.manager.config;
import io.quarkus.runtime.StartupEvent;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.junit.jupiter.MockitoExtension;
import java.lang.reflect.Field;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests unitaires pour KeycloakTestUserConfig
*/
@ExtendWith(MockitoExtension.class)
class KeycloakTestUserConfigTest {
@InjectMocks
private KeycloakTestUserConfig config;
@BeforeEach
void setUp() throws Exception {
// Injecter les propriétés via reflection
setField("profile", "dev");
setField("keycloakServerUrl", "http://localhost:8180");
setField("adminRealm", "master");
setField("adminUsername", "admin");
setField("adminPassword", "admin");
setField("authorizedRealms", "lions-user-manager");
}
private void setField(String fieldName, Object value) throws Exception {
Field field = KeycloakTestUserConfig.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(config, value);
}
@Test
void testOnStart_DevMode() {
// La méthode onStart est désactivée, elle devrait juste logger et retourner
assertDoesNotThrow(() -> {
config.onStart(new StartupEvent());
});
}
@Test
void testOnStart_ProdMode() throws Exception {
setField("profile", "prod");
// En prod, la méthode devrait retourner immédiatement
assertDoesNotThrow(() -> {
config.onStart(new StartupEvent());
});
}
@Test
void testConstants() {
// Vérifier que les constantes sont définies
assertNotNull(KeycloakTestUserConfig.class);
// Les constantes sont privées, on ne peut pas les tester directement
// mais on peut vérifier que la classe se charge correctement
}
}

View File

@@ -0,0 +1,79 @@
package dev.lions.user.manager.mapper;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import org.junit.jupiter.api.Test;
import org.keycloak.representations.idm.RoleRepresentation;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests supplémentaires pour RoleMapper pour améliorer la couverture
*/
class RoleMapperAdditionalTest {
@Test
void testToDTO_WithAllFields() {
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId("role-123");
roleRep.setName("admin");
roleRep.setDescription("Administrator role");
roleRep.setComposite(false);
RoleDTO dto = RoleMapper.toDTO(roleRep, "test-realm", TypeRole.REALM_ROLE);
assertNotNull(dto);
assertEquals("role-123", dto.getId());
assertEquals("admin", dto.getName());
assertEquals("Administrator role", dto.getDescription());
assertEquals(TypeRole.REALM_ROLE, dto.getTypeRole());
assertFalse(dto.getComposite());
}
@Test
void testToDTO_WithNullFields() {
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId("role-123");
roleRep.setName("user");
RoleDTO dto = RoleMapper.toDTO(roleRep, "test-realm", TypeRole.REALM_ROLE);
assertNotNull(dto);
assertEquals("role-123", dto.getId());
assertEquals("user", dto.getName());
assertNull(dto.getDescription());
}
@Test
void testToDTOList_Empty() {
List<RoleDTO> dtos = RoleMapper.toDTOList(Collections.emptyList(), "test-realm", TypeRole.REALM_ROLE);
assertNotNull(dtos);
assertTrue(dtos.isEmpty());
}
@Test
void testToDTOList_WithRoles() {
RoleRepresentation role1 = new RoleRepresentation();
role1.setId("role-1");
role1.setName("admin");
RoleRepresentation role2 = new RoleRepresentation();
role2.setId("role-2");
role2.setName("user");
List<RoleDTO> dtos = RoleMapper.toDTOList(Arrays.asList(role1, role2), "test-realm", TypeRole.REALM_ROLE);
assertNotNull(dtos);
assertEquals(2, dtos.size());
assertEquals("admin", dtos.get(0).getName());
assertEquals("user", dtos.get(1).getName());
}
// La méthode toKeycloak() n'existe pas dans RoleMapper
// Ces tests sont supprimés car la méthode n'est pas disponible
}

View File

@@ -0,0 +1,91 @@
package dev.lions.user.manager.mapper;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import org.junit.jupiter.api.Test;
import org.keycloak.representations.idm.RoleRepresentation;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class RoleMapperTest {
@Test
void testToDTO() {
RoleRepresentation rep = new RoleRepresentation();
rep.setId("1");
rep.setName("role");
rep.setDescription("desc");
rep.setComposite(true);
RoleDTO dto = RoleMapper.toDTO(rep, "realm", TypeRole.REALM_ROLE);
assertNotNull(dto);
assertEquals("1", dto.getId());
assertEquals("role", dto.getName());
assertEquals("desc", dto.getDescription());
assertEquals(TypeRole.REALM_ROLE, dto.getTypeRole());
assertEquals("realm", dto.getRealmName());
assertTrue(dto.getComposite());
assertNull(RoleMapper.toDTO(null, "realm", TypeRole.REALM_ROLE));
}
@Test
void testToRepresentation() {
RoleDTO dto = RoleDTO.builder()
.id("1")
.name("role")
.description("desc")
.composite(true)
.compositeRoles(Collections.singletonList("subrole"))
.typeRole(TypeRole.CLIENT_ROLE) // Should setClientRole(true)
.build();
RoleRepresentation rep = RoleMapper.toRepresentation(dto);
assertNotNull(rep);
assertEquals("1", rep.getId());
assertEquals("role", rep.getName());
assertEquals("desc", rep.getDescription());
assertTrue(rep.isComposite());
assertTrue(rep.getClientRole());
assertNull(RoleMapper.toRepresentation(null));
}
// New test case to cover full branch logic
@Test
void testToRepresentationRealmRole() {
RoleDTO dto = RoleDTO.builder()
.typeRole(TypeRole.REALM_ROLE)
.build();
RoleRepresentation rep = RoleMapper.toRepresentation(dto);
assertFalse(rep.getClientRole());
}
@Test
void testToDTOList() {
RoleRepresentation rep = new RoleRepresentation();
rep.setName("role");
List<RoleRepresentation> reps = Collections.singletonList(rep);
List<RoleDTO> dtos = RoleMapper.toDTOList(reps, "realm", TypeRole.REALM_ROLE);
assertEquals(1, dtos.size());
assertEquals("role", dtos.get(0).getName());
assertTrue(RoleMapper.toDTOList(null, "realm", TypeRole.REALM_ROLE).isEmpty());
}
@Test
void testToRepresentationList() {
RoleDTO dto = RoleDTO.builder().name("role").typeRole(TypeRole.REALM_ROLE).build();
List<RoleDTO> dtos = Collections.singletonList(dto);
List<RoleRepresentation> reps = RoleMapper.toRepresentationList(dtos);
assertEquals(1, reps.size());
assertEquals("role", reps.get(0).getName());
assertTrue(RoleMapper.toRepresentationList(null).isEmpty());
}
}

View File

@@ -0,0 +1,150 @@
package dev.lions.user.manager.mapper;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.enums.user.StatutUser;
import org.junit.jupiter.api.Test;
import org.keycloak.representations.idm.UserRepresentation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
class UserMapperTest {
@Test
void testToDTO() {
UserRepresentation rep = new UserRepresentation();
rep.setId("1");
rep.setUsername("jdoe");
rep.setEmail("jdoe@example.com");
rep.setEmailVerified(true);
rep.setFirstName("John");
rep.setLastName("Doe");
rep.setEnabled(true);
rep.setCreatedTimestamp(System.currentTimeMillis());
Map<String, List<String>> attrs = Map.of(
"phone_number", List.of("123"),
"organization", List.of("Lions"),
"department", List.of("IT"),
"job_title", List.of("Dev"),
"country", List.of("CI"),
"city", List.of("Abidjan"),
"locale", List.of("fr"),
"timezone", List.of("UTC"));
rep.setAttributes(attrs);
UserDTO dto = UserMapper.toDTO(rep, "realm");
assertNotNull(dto);
assertEquals("1", dto.getId());
assertEquals("jdoe", dto.getUsername());
assertEquals("jdoe@example.com", dto.getEmail());
assertTrue(dto.getEmailVerified());
assertEquals("John", dto.getPrenom());
assertEquals("Doe", dto.getNom());
assertEquals(StatutUser.ACTIF, dto.getStatut());
assertEquals("realm", dto.getRealmName());
assertEquals("123", dto.getTelephone());
assertEquals("Lions", dto.getOrganisation());
assertEquals("IT", dto.getDepartement());
assertEquals("Dev", dto.getFonction());
assertEquals("CI", dto.getPays());
assertEquals("Abidjan", dto.getVille());
assertEquals("fr", dto.getLangue());
assertEquals("UTC", dto.getTimezone());
assertNotNull(dto.getDateCreation());
assertNull(UserMapper.toDTO(null, "realm"));
}
@Test
void testToDTOWithNullAttributes() {
UserRepresentation rep = new UserRepresentation();
rep.setId("1");
rep.setEnabled(true);
UserDTO dto = UserMapper.toDTO(rep, "realm");
assertNotNull(dto);
assertNull(dto.getTelephone()); // Attribute missing
}
@Test
void testToDTOWithEmptyAttributes() {
UserRepresentation rep = new UserRepresentation();
rep.setEnabled(true);
rep.setAttributes(Collections.emptyMap());
UserDTO dto = UserMapper.toDTO(rep, "realm");
assertNotNull(dto);
assertNull(dto.getTelephone());
}
@Test
void testToRepresentation() {
UserDTO dto = UserDTO.builder()
.id("1")
.username("jdoe")
.email("jdoe@example.com")
.emailVerified(true)
.prenom("John")
.nom("Doe")
.enabled(true)
.telephone("123")
.organisation("Lions")
.departement("IT")
.fonction("Dev")
.pays("CI")
.ville("Abidjan")
.langue("fr")
.timezone("UTC")
.requiredActions(Collections.singletonList("UPDATE_PASSWORD"))
.attributes(Map.of("custom", List.of("value")))
.build();
UserRepresentation rep = UserMapper.toRepresentation(dto);
assertNotNull(rep);
assertEquals("1", rep.getId());
assertEquals("jdoe", rep.getUsername());
assertEquals("jdoe@example.com", rep.getEmail());
assertTrue(rep.isEmailVerified());
assertEquals("John", rep.getFirstName());
assertEquals("Doe", rep.getLastName());
assertTrue(rep.isEnabled());
assertNotNull(rep.getAttributes());
assertEquals(List.of("123"), rep.getAttributes().get("phone_number"));
assertEquals(List.of("Lions"), rep.getAttributes().get("organization"));
assertEquals(List.of("value"), rep.getAttributes().get("custom"));
assertNotNull(rep.getRequiredActions());
assertTrue(rep.getRequiredActions().contains("UPDATE_PASSWORD"));
assertNull(UserMapper.toRepresentation(null));
}
@Test
void testToRepresentationValuesNull() {
UserDTO dto = UserDTO.builder().username("jdoe").enabled(null).build();
UserRepresentation rep = UserMapper.toRepresentation(dto);
assertTrue(rep.isEnabled()); // Defaults to true in mapper
}
@Test
void testToDTOList() {
UserRepresentation rep = new UserRepresentation();
rep.setEnabled(true);
List<UserRepresentation> reps = Collections.singletonList(rep);
List<UserDTO> dtos = UserMapper.toDTOList(reps, "realm");
assertEquals(1, dtos.size());
assertTrue(UserMapper.toDTOList(null, "realm").isEmpty());
}
@Test
void testPrivateConstructor() throws Exception {
java.lang.reflect.Constructor<UserMapper> constructor = UserMapper.class.getDeclaredConstructor();
assertTrue(java.lang.reflect.Modifier.isPrivate(constructor.getModifiers()));
constructor.setAccessible(true);
assertNotNull(constructor.newInstance());
}
}

View File

@@ -0,0 +1,270 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import dev.lions.user.manager.service.AuditService;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class AuditResourceTest {
@Mock
AuditService auditService;
@InjectMocks
AuditResource auditResource;
@Test
void testSearchLogs() {
List<AuditLogDTO> logs = Collections.singletonList(
AuditLogDTO.builder().acteurUsername("admin").typeAction(TypeActionAudit.USER_CREATE).build());
when(auditService.findByActeur(eq("admin"), isNull(), isNull(), eq(0), eq(50))).thenReturn(logs);
Response response = auditResource.searchLogs("admin", null, null, null, null, null, 0, 50);
assertEquals(200, response.getStatus());
assertEquals(logs, response.getEntity());
}
@Test
void testSearchLogsWithDates() {
List<AuditLogDTO> logs = Collections.emptyList();
when(auditService.findByRealm(eq("master"), any(), any(), eq(0), eq(50))).thenReturn(logs);
Response response = auditResource.searchLogs(null, "2024-01-01T00:00:00", "2024-12-31T23:59:59",
TypeActionAudit.USER_CREATE, null, true, 0, 50);
assertEquals(200, response.getStatus());
}
@Test
void testSearchLogsError() {
when(auditService.findByRealm(eq("master"), isNull(), isNull(), eq(0), eq(50)))
.thenThrow(new RuntimeException("Error"));
Response response = auditResource.searchLogs(null, null, null, null, null, null, 0, 50);
assertEquals(500, response.getStatus());
}
@Test
void testGetLogsByActor() {
List<AuditLogDTO> logs = Collections.singletonList(
AuditLogDTO.builder().acteurUsername("admin").build());
when(auditService.findByActeur(eq("admin"), isNull(), isNull(), eq(0), eq(100))).thenReturn(logs);
Response response = auditResource.getLogsByActor("admin", 100);
assertEquals(200, response.getStatus());
assertEquals(logs, response.getEntity());
}
@Test
void testGetLogsByActorError() {
when(auditService.findByActeur(eq("admin"), isNull(), isNull(), eq(0), eq(100)))
.thenThrow(new RuntimeException("Error"));
Response response = auditResource.getLogsByActor("admin", 100);
assertEquals(500, response.getStatus());
}
@Test
void testGetLogsByResource() {
List<AuditLogDTO> logs = Collections.emptyList();
when(auditService.findByRessource(eq("USER"), eq("1"), isNull(), isNull(), eq(0), eq(100)))
.thenReturn(logs);
Response response = auditResource.getLogsByResource("USER", "1", 100);
assertEquals(200, response.getStatus());
assertEquals(logs, response.getEntity());
}
@Test
void testGetLogsByResourceError() {
when(auditService.findByRessource(eq("USER"), eq("1"), isNull(), isNull(), eq(0), eq(100)))
.thenThrow(new RuntimeException("Error"));
Response response = auditResource.getLogsByResource("USER", "1", 100);
assertEquals(500, response.getStatus());
}
@Test
void testGetLogsByAction() {
List<AuditLogDTO> logs = Collections.emptyList();
when(auditService.findByTypeAction(eq(TypeActionAudit.USER_CREATE), eq("master"), isNull(), isNull(), eq(0), eq(100)))
.thenReturn(logs);
Response response = auditResource.getLogsByAction(TypeActionAudit.USER_CREATE, null, null, 100);
assertEquals(200, response.getStatus());
}
@Test
void testGetLogsByActionWithDates() {
List<AuditLogDTO> logs = Collections.emptyList();
when(auditService.findByTypeAction(eq(TypeActionAudit.USER_UPDATE), eq("master"), any(), any(), eq(0), eq(50)))
.thenReturn(logs);
Response response = auditResource.getLogsByAction(TypeActionAudit.USER_UPDATE,
"2024-01-01T00:00:00", "2024-12-31T23:59:59", 50);
assertEquals(200, response.getStatus());
}
@Test
void testGetLogsByActionError() {
when(auditService.findByTypeAction(any(), eq("master"), any(), any(), anyInt(), anyInt()))
.thenThrow(new RuntimeException("Error"));
Response response = auditResource.getLogsByAction(TypeActionAudit.USER_CREATE, null, null, 100);
assertEquals(500, response.getStatus());
}
@Test
void testGetActionStatistics() {
Map<TypeActionAudit, Long> stats = Map.of(TypeActionAudit.USER_CREATE, 10L);
when(auditService.countByActionType(eq("master"), isNull(), isNull())).thenReturn(stats);
Response response = auditResource.getActionStatistics(null, null);
assertEquals(200, response.getStatus());
assertEquals(stats, response.getEntity());
}
@Test
void testGetActionStatisticsError() {
when(auditService.countByActionType(eq("master"), any(), any())).thenThrow(new RuntimeException("Error"));
Response response = auditResource.getActionStatistics(null, null);
assertEquals(500, response.getStatus());
}
@Test
void testGetUserActivityStatistics() {
Map<String, Long> stats = Map.of("admin", 100L);
when(auditService.countByActeur(eq("master"), isNull(), isNull())).thenReturn(stats);
Response response = auditResource.getUserActivityStatistics(null, null);
assertEquals(200, response.getStatus());
assertEquals(stats, response.getEntity());
}
@Test
void testGetUserActivityStatisticsError() {
when(auditService.countByActeur(eq("master"), any(), any())).thenThrow(new RuntimeException("Error"));
Response response = auditResource.getUserActivityStatistics(null, null);
assertEquals(500, response.getStatus());
}
@Test
void testGetFailureCount() {
Map<String, Long> successVsFailure = Map.of("failure", 5L, "success", 100L);
when(auditService.countSuccessVsFailure(eq("master"), isNull(), isNull())).thenReturn(successVsFailure);
Response response = auditResource.getFailureCount(null, null);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testGetFailureCountError() {
when(auditService.countSuccessVsFailure(eq("master"), any(), any())).thenThrow(new RuntimeException("Error"));
Response response = auditResource.getFailureCount(null, null);
assertEquals(500, response.getStatus());
}
@Test
void testGetSuccessCount() {
Map<String, Long> successVsFailure = Map.of("failure", 5L, "success", 100L);
when(auditService.countSuccessVsFailure(eq("master"), isNull(), isNull())).thenReturn(successVsFailure);
Response response = auditResource.getSuccessCount(null, null);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testGetSuccessCountError() {
when(auditService.countSuccessVsFailure(eq("master"), any(), any())).thenThrow(new RuntimeException("Error"));
Response response = auditResource.getSuccessCount(null, null);
assertEquals(500, response.getStatus());
}
@Test
void testExportLogsToCSV() {
when(auditService.exportToCSV(eq("master"), isNull(), isNull())).thenReturn("csv,data");
Response response = auditResource.exportLogsToCSV(null, null);
assertEquals(200, response.getStatus());
}
@Test
void testExportLogsToCSVError() {
when(auditService.exportToCSV(eq("master"), any(), any())).thenThrow(new RuntimeException("Error"));
Response response = auditResource.exportLogsToCSV(null, null);
assertEquals(500, response.getStatus());
}
@Test
void testPurgeOldLogs() {
when(auditService.purgeOldLogs(any())).thenReturn(50L);
Response response = auditResource.purgeOldLogs(90);
assertEquals(204, response.getStatus());
}
@Test
void testPurgeOldLogsError() {
when(auditService.purgeOldLogs(any())).thenThrow(new RuntimeException("Error"));
Response response = auditResource.purgeOldLogs(90);
assertEquals(500, response.getStatus());
}
// ============== Inner Class Tests ==============
@Test
void testCountResponseClass() {
AuditResource.CountResponse response = new AuditResource.CountResponse(42);
assertEquals(42, response.count);
}
@Test
void testErrorResponseClass() {
AuditResource.ErrorResponse response = new AuditResource.ErrorResponse("Error message");
assertEquals("Error message", response.message);
}
}

View File

@@ -0,0 +1,99 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.client.KeycloakAdminClient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class HealthResourceEndpointTest {
@Mock
KeycloakAdminClient keycloakAdminClient;
@Mock
Keycloak keycloak;
@InjectMocks
HealthResourceEndpoint healthResourceEndpoint;
@Test
void testGetKeycloakHealthConnected() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloak);
Map<String, Object> result = healthResourceEndpoint.getKeycloakHealth();
assertNotNull(result);
assertEquals("UP", result.get("status"));
assertEquals(true, result.get("connected"));
assertNotNull(result.get("timestamp"));
}
@Test
void testGetKeycloakHealthDisconnected() {
when(keycloakAdminClient.getInstance()).thenReturn(null);
Map<String, Object> result = healthResourceEndpoint.getKeycloakHealth();
assertNotNull(result);
assertEquals("DOWN", result.get("status"));
assertEquals(false, result.get("connected"));
}
@Test
void testGetKeycloakHealthError() {
when(keycloakAdminClient.getInstance()).thenThrow(new RuntimeException("Connection error"));
Map<String, Object> result = healthResourceEndpoint.getKeycloakHealth();
assertNotNull(result);
assertEquals("ERROR", result.get("status"));
assertEquals(false, result.get("connected"));
assertEquals("Connection error", result.get("error"));
}
@Test
void testGetServiceStatusConnected() {
when(keycloakAdminClient.isConnected()).thenReturn(true);
Map<String, Object> result = healthResourceEndpoint.getServiceStatus();
assertNotNull(result);
assertEquals("lions-user-manager-server", result.get("service"));
assertEquals("1.0.0", result.get("version"));
assertEquals("UP", result.get("status"));
assertEquals("CONNECTED", result.get("keycloak"));
assertNotNull(result.get("timestamp"));
}
@Test
void testGetServiceStatusDisconnected() {
when(keycloakAdminClient.isConnected()).thenReturn(false);
Map<String, Object> result = healthResourceEndpoint.getServiceStatus();
assertNotNull(result);
assertEquals("UP", result.get("status"));
assertEquals("DISCONNECTED", result.get("keycloak"));
}
@Test
void testGetServiceStatusKeycloakError() {
when(keycloakAdminClient.isConnected()).thenThrow(new RuntimeException("Error"));
Map<String, Object> result = healthResourceEndpoint.getServiceStatus();
assertNotNull(result);
assertEquals("UP", result.get("status"));
assertEquals("ERROR", result.get("keycloak"));
assertEquals("Error", result.get("keycloakError"));
}
}

View File

@@ -0,0 +1,224 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
import dev.lions.user.manager.service.RealmAuthorizationService;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.SecurityContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.security.Principal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests unitaires pour RealmAssignmentResource
*/
@ExtendWith(MockitoExtension.class)
class RealmAssignmentResourceTest {
@Mock
private RealmAuthorizationService realmAuthorizationService;
@Mock
private SecurityContext securityContext;
@Mock
private Principal principal;
@InjectMocks
private RealmAssignmentResource realmAssignmentResource;
private RealmAssignmentDTO assignment;
@BeforeEach
void setUp() {
assignment = RealmAssignmentDTO.builder()
.id("assignment-1")
.userId("user-1")
.username("testuser")
.email("test@example.com")
.realmName("realm1")
.isSuperAdmin(false)
.active(true)
.assignedAt(LocalDateTime.now())
.assignedBy("admin")
.build();
}
@Test
void testGetAllAssignments_Success() {
List<RealmAssignmentDTO> assignments = Arrays.asList(assignment);
when(realmAuthorizationService.getAllAssignments()).thenReturn(assignments);
Response response = realmAssignmentResource.getAllAssignments();
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
@SuppressWarnings("unchecked")
List<RealmAssignmentDTO> responseAssignments = (List<RealmAssignmentDTO>) response.getEntity();
assertEquals(1, responseAssignments.size());
}
@Test
void testGetAllAssignments_Error() {
when(realmAuthorizationService.getAllAssignments()).thenThrow(new RuntimeException("Error"));
Response response = realmAssignmentResource.getAllAssignments();
assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
}
@Test
void testGetAssignmentsByUser_Success() {
List<RealmAssignmentDTO> assignments = Arrays.asList(assignment);
when(realmAuthorizationService.getAssignmentsByUser("user-1")).thenReturn(assignments);
Response response = realmAssignmentResource.getAssignmentsByUser("user-1");
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
}
@Test
void testGetAssignmentsByRealm_Success() {
List<RealmAssignmentDTO> assignments = Arrays.asList(assignment);
when(realmAuthorizationService.getAssignmentsByRealm("realm1")).thenReturn(assignments);
Response response = realmAssignmentResource.getAssignmentsByRealm("realm1");
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
}
@Test
void testGetAssignmentById_Success() {
when(realmAuthorizationService.getAssignmentById("assignment-1")).thenReturn(Optional.of(assignment));
Response response = realmAssignmentResource.getAssignmentById("assignment-1");
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
}
@Test
void testGetAssignmentById_NotFound() {
when(realmAuthorizationService.getAssignmentById("non-existent")).thenReturn(Optional.empty());
Response response = realmAssignmentResource.getAssignmentById("non-existent");
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
}
@Test
void testCanManageRealm_Success() {
when(realmAuthorizationService.canManageRealm("user-1", "realm1")).thenReturn(true);
Response response = realmAssignmentResource.canManageRealm("user-1", "realm1");
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
RealmAssignmentResource.CheckResponse checkResponse = (RealmAssignmentResource.CheckResponse) response.getEntity();
assertTrue(checkResponse.canManage);
}
@Test
void testGetAuthorizedRealms_Success() {
List<String> realms = Arrays.asList("realm1", "realm2");
when(realmAuthorizationService.getAuthorizedRealms("user-1")).thenReturn(realms);
when(realmAuthorizationService.isSuperAdmin("user-1")).thenReturn(false);
Response response = realmAssignmentResource.getAuthorizedRealms("user-1");
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
RealmAssignmentResource.AuthorizedRealmsResponse authResponse =
(RealmAssignmentResource.AuthorizedRealmsResponse) response.getEntity();
assertEquals(2, authResponse.realms.size());
assertFalse(authResponse.isSuperAdmin);
}
@Test
void testAssignRealmToUser_Success() {
when(securityContext.getUserPrincipal()).thenReturn(principal);
when(principal.getName()).thenReturn("admin");
when(realmAuthorizationService.assignRealmToUser(any(RealmAssignmentDTO.class))).thenReturn(assignment);
Response response = realmAssignmentResource.assignRealmToUser(assignment);
assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());
}
@Test
void testAssignRealmToUser_Conflict() {
when(securityContext.getUserPrincipal()).thenReturn(principal);
when(principal.getName()).thenReturn("admin");
when(realmAuthorizationService.assignRealmToUser(any(RealmAssignmentDTO.class)))
.thenThrow(new IllegalArgumentException("Already exists"));
Response response = realmAssignmentResource.assignRealmToUser(assignment);
assertEquals(Response.Status.CONFLICT.getStatusCode(), response.getStatus());
}
@Test
void testRevokeRealmFromUser_Success() {
doNothing().when(realmAuthorizationService).revokeRealmFromUser("user-1", "realm1");
Response response = realmAssignmentResource.revokeRealmFromUser("user-1", "realm1");
assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
}
@Test
void testRevokeAllRealmsFromUser_Success() {
doNothing().when(realmAuthorizationService).revokeAllRealmsFromUser("user-1");
Response response = realmAssignmentResource.revokeAllRealmsFromUser("user-1");
assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
}
@Test
void testDeactivateAssignment_Success() {
doNothing().when(realmAuthorizationService).deactivateAssignment("assignment-1");
Response response = realmAssignmentResource.deactivateAssignment("assignment-1");
assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
}
@Test
void testDeactivateAssignment_NotFound() {
doThrow(new IllegalArgumentException("Not found"))
.when(realmAuthorizationService).deactivateAssignment("non-existent");
Response response = realmAssignmentResource.deactivateAssignment("non-existent");
assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
}
@Test
void testActivateAssignment_Success() {
doNothing().when(realmAuthorizationService).activateAssignment("assignment-1");
Response response = realmAssignmentResource.activateAssignment("assignment-1");
assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
}
@Test
void testSetSuperAdmin_Success() {
doNothing().when(realmAuthorizationService).setSuperAdmin("user-1", true);
Response response = realmAssignmentResource.setSuperAdmin("user-1", true);
assertEquals(Response.Status.NO_CONTENT.getStatusCode(), response.getStatus());
}
}

View File

@@ -0,0 +1,73 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.client.KeycloakAdminClient;
import io.quarkus.security.identity.SecurityIdentity;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* Tests supplémentaires pour RealmResource pour améliorer la couverture
*/
@ExtendWith(MockitoExtension.class)
class RealmResourceAdditionalTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private SecurityIdentity securityIdentity;
@InjectMocks
private RealmResource realmResource;
@BeforeEach
void setUp() {
// Setup
}
@Test
void testGetAllRealms_Success() {
List<String> realms = Arrays.asList("master", "lions-user-manager", "test-realm");
when(keycloakAdminClient.getAllRealms()).thenReturn(realms);
Response response = realmResource.getAllRealms();
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
@SuppressWarnings("unchecked")
List<String> responseRealms = (List<String>) response.getEntity();
assertEquals(3, responseRealms.size());
}
@Test
void testGetAllRealms_Empty() {
when(keycloakAdminClient.getAllRealms()).thenReturn(List.of());
Response response = realmResource.getAllRealms();
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
@SuppressWarnings("unchecked")
List<String> responseRealms = (List<String>) response.getEntity();
assertTrue(responseRealms.isEmpty());
}
@Test
void testGetAllRealms_Exception() {
when(keycloakAdminClient.getAllRealms()).thenThrow(new RuntimeException("Connection error"));
Response response = realmResource.getAllRealms();
assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
}
}

View File

@@ -0,0 +1,90 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.client.KeycloakAdminClient;
import io.quarkus.security.identity.SecurityIdentity;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import jakarta.ws.rs.core.Response;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* Tests unitaires pour RealmResource
*/
@ExtendWith(MockitoExtension.class)
class RealmResourceTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private SecurityIdentity securityIdentity;
@InjectMocks
private RealmResource realmResource;
@BeforeEach
void setUp() {
// Setup initial
}
@Test
void testGetAllRealms_Success() {
List<String> realms = Arrays.asList("master", "lions-user-manager", "btpxpress");
when(keycloakAdminClient.getAllRealms()).thenReturn(realms);
Response response = realmResource.getAllRealms();
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
@SuppressWarnings("unchecked")
List<String> responseRealms = (List<String>) response.getEntity();
assertNotNull(responseRealms);
assertEquals(3, responseRealms.size());
assertEquals("master", responseRealms.get(0));
verify(keycloakAdminClient).getAllRealms();
}
@Test
void testGetAllRealms_EmptyList() {
when(keycloakAdminClient.getAllRealms()).thenReturn(Collections.emptyList());
Response response = realmResource.getAllRealms();
assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
@SuppressWarnings("unchecked")
List<String> responseRealms = (List<String>) response.getEntity();
assertNotNull(responseRealms);
assertTrue(responseRealms.isEmpty());
}
@Test
void testGetAllRealms_Exception() {
when(keycloakAdminClient.getAllRealms()).thenThrow(new RuntimeException("Keycloak connection error"));
Response response = realmResource.getAllRealms();
assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
RealmResource.ErrorResponse errorResponse = (RealmResource.ErrorResponse) response.getEntity();
assertNotNull(errorResponse);
assertTrue(errorResponse.getMessage().contains("Erreur lors de la récupération des realms"));
}
@Test
void testErrorResponse() {
RealmResource.ErrorResponse errorResponse = new RealmResource.ErrorResponse("Test error");
assertEquals("Test error", errorResponse.getMessage());
errorResponse.setMessage("New error");
assertEquals("New error", errorResponse.getMessage());
}
}

View File

@@ -0,0 +1,541 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.dto.role.RoleAssignmentDTO;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import dev.lions.user.manager.service.RoleService;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class RoleResourceTest {
@Mock
RoleService roleService;
@InjectMocks
RoleResource roleResource;
private static final String REALM = "test-realm";
private static final String CLIENT_ID = "test-client";
// ============== Realm Role Tests ==============
@Test
void testCreateRealmRole() {
RoleDTO input = RoleDTO.builder().name("role").description("desc").build();
RoleDTO created = RoleDTO.builder().id("1").name("role").description("desc").build();
when(roleService.createRealmRole(any(), eq(REALM))).thenReturn(created);
Response response = roleResource.createRealmRole(input, REALM);
assertEquals(201, response.getStatus());
assertEquals(created, response.getEntity());
}
@Test
void testCreateRealmRoleConflict() {
RoleDTO input = RoleDTO.builder().name("role").build();
when(roleService.createRealmRole(any(), eq(REALM)))
.thenThrow(new IllegalArgumentException("Role already exists"));
Response response = roleResource.createRealmRole(input, REALM);
assertEquals(409, response.getStatus());
}
@Test
void testCreateRealmRoleError() {
RoleDTO input = RoleDTO.builder().name("role").build();
when(roleService.createRealmRole(any(), eq(REALM)))
.thenThrow(new RuntimeException("Error"));
Response response = roleResource.createRealmRole(input, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetRealmRole() {
RoleDTO role = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(role));
Response response = roleResource.getRealmRole("role", REALM);
assertEquals(200, response.getStatus());
assertEquals(role, response.getEntity());
}
@Test
void testGetRealmRoleNotFound() {
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.empty());
Response response = roleResource.getRealmRole("role", REALM);
assertEquals(404, response.getStatus());
}
@Test
void testGetRealmRoleError() {
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenThrow(new RuntimeException("Error"));
Response response = roleResource.getRealmRole("role", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetAllRealmRoles() {
List<RoleDTO> roles = Collections.singletonList(RoleDTO.builder().name("role").build());
when(roleService.getAllRealmRoles(REALM)).thenReturn(roles);
Response response = roleResource.getAllRealmRoles(REALM);
assertEquals(200, response.getStatus());
assertEquals(roles, response.getEntity());
}
@Test
void testGetAllRealmRolesError() {
when(roleService.getAllRealmRoles(REALM)).thenThrow(new RuntimeException("Error"));
Response response = roleResource.getAllRealmRoles(REALM);
assertEquals(500, response.getStatus());
}
@Test
void testUpdateRealmRole() {
RoleDTO existingRole = RoleDTO.builder().id("1").name("role").build();
RoleDTO input = RoleDTO.builder().description("updated").build();
RoleDTO updated = RoleDTO.builder().id("1").name("role").description("updated").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(existingRole));
when(roleService.updateRole(eq("1"), any(), eq(REALM), eq(TypeRole.REALM_ROLE), isNull()))
.thenReturn(updated);
Response response = roleResource.updateRealmRole("role", input, REALM);
assertEquals(200, response.getStatus());
assertEquals(updated, response.getEntity());
}
@Test
void testUpdateRealmRoleNotFound() {
RoleDTO input = RoleDTO.builder().description("updated").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.empty());
Response response = roleResource.updateRealmRole("role", input, REALM);
assertEquals(404, response.getStatus());
}
@Test
void testUpdateRealmRoleError() {
RoleDTO existingRole = RoleDTO.builder().id("1").name("role").build();
RoleDTO input = RoleDTO.builder().description("updated").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(existingRole));
when(roleService.updateRole(eq("1"), any(), eq(REALM), eq(TypeRole.REALM_ROLE), isNull()))
.thenThrow(new RuntimeException("Error"));
Response response = roleResource.updateRealmRole("role", input, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testDeleteRealmRole() {
RoleDTO existingRole = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(existingRole));
doNothing().when(roleService).deleteRole(eq("1"), eq(REALM), eq(TypeRole.REALM_ROLE), isNull());
Response response = roleResource.deleteRealmRole("role", REALM);
assertEquals(204, response.getStatus());
}
@Test
void testDeleteRealmRoleNotFound() {
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.empty());
Response response = roleResource.deleteRealmRole("role", REALM);
assertEquals(404, response.getStatus());
}
@Test
void testDeleteRealmRoleError() {
RoleDTO existingRole = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(existingRole));
doThrow(new RuntimeException("Error")).when(roleService)
.deleteRole(eq("1"), eq(REALM), eq(TypeRole.REALM_ROLE), isNull());
Response response = roleResource.deleteRealmRole("role", REALM);
assertEquals(500, response.getStatus());
}
// ============== Client Role Tests ==============
@Test
void testCreateClientRole() {
RoleDTO input = RoleDTO.builder().name("role").build();
RoleDTO created = RoleDTO.builder().id("1").name("role").build();
when(roleService.createClientRole(any(RoleDTO.class), eq(REALM), eq(CLIENT_ID))).thenReturn(created);
Response response = roleResource.createClientRole(CLIENT_ID, input, REALM);
assertEquals(201, response.getStatus());
assertEquals(created, response.getEntity());
}
@Test
void testCreateClientRoleError() {
RoleDTO input = RoleDTO.builder().name("role").build();
when(roleService.createClientRole(any(RoleDTO.class), eq(REALM), eq(CLIENT_ID)))
.thenThrow(new RuntimeException("Error"));
Response response = roleResource.createClientRole(CLIENT_ID, input, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetClientRole() {
RoleDTO role = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.CLIENT_ROLE, CLIENT_ID))
.thenReturn(Optional.of(role));
Response response = roleResource.getClientRole(CLIENT_ID, "role", REALM);
assertEquals(200, response.getStatus());
assertEquals(role, response.getEntity());
}
@Test
void testGetClientRoleNotFound() {
when(roleService.getRoleByName("role", REALM, TypeRole.CLIENT_ROLE, CLIENT_ID))
.thenReturn(Optional.empty());
Response response = roleResource.getClientRole(CLIENT_ID, "role", REALM);
assertEquals(404, response.getStatus());
}
@Test
void testGetClientRoleError() {
when(roleService.getRoleByName("role", REALM, TypeRole.CLIENT_ROLE, CLIENT_ID))
.thenThrow(new RuntimeException("Error"));
Response response = roleResource.getClientRole(CLIENT_ID, "role", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetAllClientRoles() {
List<RoleDTO> roles = Collections.singletonList(RoleDTO.builder().name("role").build());
when(roleService.getAllClientRoles(REALM, CLIENT_ID)).thenReturn(roles);
Response response = roleResource.getAllClientRoles(CLIENT_ID, REALM);
assertEquals(200, response.getStatus());
assertEquals(roles, response.getEntity());
}
@Test
void testGetAllClientRolesError() {
when(roleService.getAllClientRoles(REALM, CLIENT_ID)).thenThrow(new RuntimeException("Error"));
Response response = roleResource.getAllClientRoles(CLIENT_ID, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testDeleteClientRole() {
RoleDTO existingRole = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.CLIENT_ROLE, CLIENT_ID))
.thenReturn(Optional.of(existingRole));
doNothing().when(roleService).deleteRole(eq("1"), eq(REALM), eq(TypeRole.CLIENT_ROLE), eq(CLIENT_ID));
Response response = roleResource.deleteClientRole(CLIENT_ID, "role", REALM);
assertEquals(204, response.getStatus());
}
@Test
void testDeleteClientRoleNotFound() {
when(roleService.getRoleByName("role", REALM, TypeRole.CLIENT_ROLE, CLIENT_ID))
.thenReturn(Optional.empty());
Response response = roleResource.deleteClientRole(CLIENT_ID, "role", REALM);
assertEquals(404, response.getStatus());
}
@Test
void testDeleteClientRoleError() {
RoleDTO existingRole = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.CLIENT_ROLE, CLIENT_ID))
.thenReturn(Optional.of(existingRole));
doThrow(new RuntimeException("Error")).when(roleService)
.deleteRole(eq("1"), eq(REALM), eq(TypeRole.CLIENT_ROLE), eq(CLIENT_ID));
Response response = roleResource.deleteClientRole(CLIENT_ID, "role", REALM);
assertEquals(500, response.getStatus());
}
// ============== Role Assignment Tests ==============
@Test
void testAssignRealmRoles() {
doNothing().when(roleService).assignRolesToUser(any(RoleAssignmentDTO.class));
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("role");
Response response = roleResource.assignRealmRoles("user1", REALM, request);
assertEquals(204, response.getStatus());
verify(roleService).assignRolesToUser(any(RoleAssignmentDTO.class));
}
@Test
void testAssignRealmRolesError() {
doThrow(new RuntimeException("Error")).when(roleService).assignRolesToUser(any(RoleAssignmentDTO.class));
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("role");
Response response = roleResource.assignRealmRoles("user1", REALM, request);
assertEquals(500, response.getStatus());
}
@Test
void testRevokeRealmRoles() {
doNothing().when(roleService).revokeRolesFromUser(any(RoleAssignmentDTO.class));
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("role");
Response response = roleResource.revokeRealmRoles("user1", REALM, request);
assertEquals(204, response.getStatus());
verify(roleService).revokeRolesFromUser(any(RoleAssignmentDTO.class));
}
@Test
void testRevokeRealmRolesError() {
doThrow(new RuntimeException("Error")).when(roleService).revokeRolesFromUser(any(RoleAssignmentDTO.class));
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("role");
Response response = roleResource.revokeRealmRoles("user1", REALM, request);
assertEquals(500, response.getStatus());
}
@Test
void testAssignClientRoles() {
doNothing().when(roleService).assignRolesToUser(any(RoleAssignmentDTO.class));
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("role");
Response response = roleResource.assignClientRoles(CLIENT_ID, "user1", REALM, request);
assertEquals(204, response.getStatus());
verify(roleService).assignRolesToUser(any(RoleAssignmentDTO.class));
}
@Test
void testAssignClientRolesError() {
doThrow(new RuntimeException("Error")).when(roleService).assignRolesToUser(any(RoleAssignmentDTO.class));
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("role");
Response response = roleResource.assignClientRoles(CLIENT_ID, "user1", REALM, request);
assertEquals(500, response.getStatus());
}
@Test
void testGetUserRealmRoles() {
List<RoleDTO> roles = Collections.singletonList(RoleDTO.builder().name("role").build());
when(roleService.getUserRealmRoles("user1", REALM)).thenReturn(roles);
Response response = roleResource.getUserRealmRoles("user1", REALM);
assertEquals(200, response.getStatus());
assertEquals(roles, response.getEntity());
}
@Test
void testGetUserRealmRolesError() {
when(roleService.getUserRealmRoles("user1", REALM)).thenThrow(new RuntimeException("Error"));
Response response = roleResource.getUserRealmRoles("user1", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetUserClientRoles() {
List<RoleDTO> roles = Collections.singletonList(RoleDTO.builder().name("role").build());
when(roleService.getUserClientRoles("user1", CLIENT_ID, REALM)).thenReturn(roles);
Response response = roleResource.getUserClientRoles(CLIENT_ID, "user1", REALM);
assertEquals(200, response.getStatus());
assertEquals(roles, response.getEntity());
}
@Test
void testGetUserClientRolesError() {
when(roleService.getUserClientRoles("user1", CLIENT_ID, REALM)).thenThrow(new RuntimeException("Error"));
Response response = roleResource.getUserClientRoles(CLIENT_ID, "user1", REALM);
assertEquals(500, response.getStatus());
}
// ============== Composite Role Tests ==============
@Test
void testAddComposites() {
RoleDTO parentRole = RoleDTO.builder().id("parent-1").name("role").build();
RoleDTO childRole = RoleDTO.builder().id("child-1").name("composite").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(parentRole));
when(roleService.getRoleByName("composite", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(childRole));
doNothing().when(roleService).addCompositeRoles(eq("parent-1"), anyList(), eq(REALM),
eq(TypeRole.REALM_ROLE), isNull());
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("composite");
Response response = roleResource.addComposites("role", REALM, request);
assertEquals(204, response.getStatus());
verify(roleService).addCompositeRoles(eq("parent-1"), anyList(), eq(REALM),
eq(TypeRole.REALM_ROLE), isNull());
}
@Test
void testAddCompositesParentNotFound() {
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.empty());
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("composite");
Response response = roleResource.addComposites("role", REALM, request);
assertEquals(404, response.getStatus());
}
@Test
void testAddCompositesError() {
RoleDTO parentRole = RoleDTO.builder().id("parent-1").name("role").build();
RoleDTO childRole = RoleDTO.builder().id("child-1").name("composite").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(parentRole));
when(roleService.getRoleByName("composite", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(childRole));
doThrow(new RuntimeException("Error")).when(roleService).addCompositeRoles(eq("parent-1"), anyList(),
eq(REALM), eq(TypeRole.REALM_ROLE), isNull());
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = Collections.singletonList("composite");
Response response = roleResource.addComposites("role", REALM, request);
assertEquals(500, response.getStatus());
}
@Test
void testGetComposites() {
RoleDTO role = RoleDTO.builder().id("1").name("role").build();
List<RoleDTO> composites = Collections.singletonList(RoleDTO.builder().name("composite").build());
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(role));
when(roleService.getCompositeRoles("1", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(composites);
Response response = roleResource.getComposites("role", REALM);
assertEquals(200, response.getStatus());
assertEquals(composites, response.getEntity());
}
@Test
void testGetCompositesNotFound() {
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.empty());
Response response = roleResource.getComposites("role", REALM);
assertEquals(404, response.getStatus());
}
@Test
void testGetCompositesError() {
RoleDTO role = RoleDTO.builder().id("1").name("role").build();
when(roleService.getRoleByName("role", REALM, TypeRole.REALM_ROLE, null))
.thenReturn(Optional.of(role));
when(roleService.getCompositeRoles("1", REALM, TypeRole.REALM_ROLE, null))
.thenThrow(new RuntimeException("Error"));
Response response = roleResource.getComposites("role", REALM);
assertEquals(500, response.getStatus());
}
// ============== Inner Class Tests ==============
@Test
void testRoleAssignmentRequestClass() {
RoleResource.RoleAssignmentRequest request = new RoleResource.RoleAssignmentRequest();
request.roleNames = List.of("role1", "role2");
assertEquals(2, request.roleNames.size());
assertTrue(request.roleNames.contains("role1"));
}
}

View File

@@ -0,0 +1,253 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.service.SyncService;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class SyncResourceTest {
@Mock
SyncService syncService;
@InjectMocks
SyncResource syncResource;
private static final String REALM = "test-realm";
private static final String CLIENT_ID = "test-client";
@Test
void testSyncUsers() {
when(syncService.syncUsersFromRealm(REALM)).thenReturn(10);
Response response = syncResource.syncUsers(REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testSyncUsersError() {
when(syncService.syncUsersFromRealm(REALM)).thenThrow(new RuntimeException("Error"));
Response response = syncResource.syncUsers(REALM);
assertEquals(500, response.getStatus());
}
@Test
void testSyncRealmRoles() {
when(syncService.syncRolesFromRealm(REALM)).thenReturn(5);
Response response = syncResource.syncRealmRoles(REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testSyncRealmRolesError() {
when(syncService.syncRolesFromRealm(REALM)).thenThrow(new RuntimeException("Error"));
Response response = syncResource.syncRealmRoles(REALM);
assertEquals(500, response.getStatus());
}
@Test
void testSyncClientRoles() {
when(syncService.syncRolesFromRealm(REALM)).thenReturn(3);
Response response = syncResource.syncClientRoles(CLIENT_ID, REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testSyncClientRolesError() {
when(syncService.syncRolesFromRealm(REALM)).thenThrow(new RuntimeException("Error"));
Response response = syncResource.syncClientRoles(CLIENT_ID, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testSyncAll() {
Map<String, Object> result = Map.of(
"realmName", REALM,
"usersSynced", 10,
"rolesSynced", 5,
"success", true
);
when(syncService.forceSyncRealm(REALM)).thenReturn(result);
Response response = syncResource.syncAll(REALM);
assertEquals(200, response.getStatus());
assertEquals(result, response.getEntity());
}
@Test
void testSyncAllError() {
when(syncService.forceSyncRealm(REALM)).thenThrow(new RuntimeException("Error"));
Response response = syncResource.syncAll(REALM);
assertEquals(500, response.getStatus());
}
@Test
void testCheckHealthHealthy() {
when(syncService.isKeycloakAvailable()).thenReturn(true);
Response response = syncResource.checkHealth();
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testCheckHealthUnhealthy() {
when(syncService.isKeycloakAvailable()).thenReturn(false);
Response response = syncResource.checkHealth();
assertEquals(503, response.getStatus());
}
@Test
void testCheckHealthError() {
when(syncService.isKeycloakAvailable()).thenThrow(new RuntimeException("Error"));
Response response = syncResource.checkHealth();
assertEquals(503, response.getStatus());
}
@Test
void testGetDetailedHealthStatus() {
Map<String, Object> status = Map.of(
"keycloakAvailable", true,
"keycloakVersion", "21.0.0"
);
when(syncService.getKeycloakHealthInfo()).thenReturn(status);
Response response = syncResource.getDetailedHealthStatus();
assertEquals(200, response.getStatus());
assertEquals(status, response.getEntity());
}
@Test
void testGetDetailedHealthStatusError() {
when(syncService.getKeycloakHealthInfo()).thenThrow(new RuntimeException("Error"));
Response response = syncResource.getDetailedHealthStatus();
assertEquals(500, response.getStatus());
}
@Test
void testCheckRealmExistsTrue() {
when(syncService.syncUsersFromRealm(REALM)).thenReturn(5);
Response response = syncResource.checkRealmExists(REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testCheckRealmExistsFalse() {
when(syncService.syncUsersFromRealm(REALM)).thenThrow(new RuntimeException("Realm not found"));
Response response = syncResource.checkRealmExists(REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testCheckRealmExistsError() {
when(syncService.syncUsersFromRealm(REALM)).thenThrow(new RuntimeException("Unexpected error"));
Response response = syncResource.checkRealmExists(REALM);
// checkRealmExists catches all exceptions and returns 200 with exists=false
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testCheckUserExists() {
// La méthode checkUserExists retourne toujours false dans l'implémentation actuelle
Response response = syncResource.checkUserExists("user1", REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testCheckUserExistsError() {
// Test d'erreur si une exception est levée
// Note: L'implémentation actuelle ne lève pas d'exception, mais testons quand même
Response response = syncResource.checkUserExists("user1", REALM);
assertEquals(200, response.getStatus());
}
// ============== Inner Class Tests ==============
@Test
void testSyncUsersResponseClass() {
SyncResource.SyncUsersResponse response = new SyncResource.SyncUsersResponse(1, null);
assertEquals(1, response.count);
assertNull(response.users);
}
@Test
void testSyncRolesResponseClass() {
SyncResource.SyncRolesResponse response = new SyncResource.SyncRolesResponse(1, null);
assertEquals(1, response.count);
assertNull(response.roles);
}
@Test
void testHealthCheckResponseClass() {
SyncResource.HealthCheckResponse response = new SyncResource.HealthCheckResponse(true, "OK");
assertTrue(response.healthy);
assertEquals("OK", response.message);
}
@Test
void testExistsCheckResponseClass() {
SyncResource.ExistsCheckResponse response = new SyncResource.ExistsCheckResponse(true, "realm", "test");
assertTrue(response.exists);
assertEquals("realm", response.resourceType);
assertEquals("test", response.resourceId);
}
@Test
void testErrorResponseClass() {
SyncResource.ErrorResponse response = new SyncResource.ErrorResponse("Error");
assertEquals("Error", response.message);
}
}

View File

@@ -0,0 +1,353 @@
package dev.lions.user.manager.resource;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import dev.lions.user.manager.service.UserService;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserResourceTest {
@Mock
UserService userService;
@InjectMocks
UserResource userResource;
private static final String REALM = "test-realm";
@Test
void testSearchUsers() {
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.searchTerm("test")
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO mockResult = UserSearchResultDTO.builder()
.users(Collections.singletonList(UserDTO.builder().username("test").build()))
.totalCount(1L)
.build();
when(userService.searchUsers(any())).thenReturn(mockResult);
Response response = userResource.searchUsers(criteria);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testSearchUsersError() {
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.build();
when(userService.searchUsers(any())).thenThrow(new RuntimeException("Search failed"));
Response response = userResource.searchUsers(criteria);
assertEquals(500, response.getStatus());
}
@Test
void testGetUserById() {
UserDTO user = UserDTO.builder().id("1").username("testuser").build();
when(userService.getUserById("1", REALM)).thenReturn(Optional.of(user));
Response response = userResource.getUserById("1", REALM);
assertEquals(200, response.getStatus());
assertEquals(user, response.getEntity());
}
@Test
void testGetUserByIdNotFound() {
when(userService.getUserById("1", REALM)).thenReturn(Optional.empty());
Response response = userResource.getUserById("1", REALM);
assertEquals(404, response.getStatus());
}
@Test
void testGetUserByIdError() {
when(userService.getUserById("1", REALM)).thenThrow(new RuntimeException("Error"));
Response response = userResource.getUserById("1", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetAllUsers() {
UserSearchResultDTO mockResult = UserSearchResultDTO.builder()
.users(Collections.emptyList())
.totalCount(0L)
.build();
when(userService.getAllUsers(REALM, 0, 20)).thenReturn(mockResult);
Response response = userResource.getAllUsers(REALM, 0, 20);
assertEquals(200, response.getStatus());
}
@Test
void testGetAllUsersError() {
when(userService.getAllUsers(REALM, 0, 20)).thenThrow(new RuntimeException("Error"));
Response response = userResource.getAllUsers(REALM, 0, 20);
assertEquals(500, response.getStatus());
}
@Test
void testCreateUser() {
UserDTO newUser = UserDTO.builder().username("newuser").email("new@test.com").build();
UserDTO createdUser = UserDTO.builder().id("123").username("newuser").email("new@test.com").build();
when(userService.createUser(any(), eq(REALM))).thenReturn(createdUser);
Response response = userResource.createUser(newUser, REALM);
assertEquals(201, response.getStatus());
assertEquals(createdUser, response.getEntity());
}
@Test
void testCreateUserError() {
UserDTO newUser = UserDTO.builder().username("newuser").email("new@test.com").build();
when(userService.createUser(any(), eq(REALM))).thenThrow(new RuntimeException("Create failed"));
Response response = userResource.createUser(newUser, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testUpdateUser() {
UserDTO updateUser = UserDTO.builder()
.username("updated")
.prenom("John")
.nom("Doe")
.email("john.doe@test.com")
.build();
UserDTO updatedUser = UserDTO.builder()
.id("1")
.username("updated")
.prenom("John")
.nom("Doe")
.email("john.doe@test.com")
.build();
when(userService.updateUser(eq("1"), any(), eq(REALM))).thenReturn(updatedUser);
Response response = userResource.updateUser("1", updateUser, REALM);
assertEquals(200, response.getStatus());
assertEquals(updatedUser, response.getEntity());
}
@Test
void testUpdateUserError() {
UserDTO updateUser = UserDTO.builder()
.username("updated")
.prenom("John")
.nom("Doe")
.email("john.doe@test.com")
.build();
when(userService.updateUser(eq("1"), any(), eq(REALM))).thenThrow(new RuntimeException("Update failed"));
Response response = userResource.updateUser("1", updateUser, REALM);
assertEquals(500, response.getStatus());
}
@Test
void testDeleteUser() {
doNothing().when(userService).deleteUser("1", REALM, false);
Response response = userResource.deleteUser("1", REALM, false);
assertEquals(204, response.getStatus());
verify(userService).deleteUser("1", REALM, false);
}
@Test
void testDeleteUserHard() {
doNothing().when(userService).deleteUser("1", REALM, true);
Response response = userResource.deleteUser("1", REALM, true);
assertEquals(204, response.getStatus());
verify(userService).deleteUser("1", REALM, true);
}
@Test
void testDeleteUserError() {
doThrow(new RuntimeException("Delete failed")).when(userService).deleteUser("1", REALM, false);
Response response = userResource.deleteUser("1", REALM, false);
assertEquals(500, response.getStatus());
}
@Test
void testActivateUser() {
doNothing().when(userService).activateUser("1", REALM);
Response response = userResource.activateUser("1", REALM);
assertEquals(204, response.getStatus());
verify(userService).activateUser("1", REALM);
}
@Test
void testActivateUserError() {
doThrow(new RuntimeException("Activate failed")).when(userService).activateUser("1", REALM);
Response response = userResource.activateUser("1", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testDeactivateUser() {
doNothing().when(userService).deactivateUser("1", REALM, "reason");
Response response = userResource.deactivateUser("1", REALM, "reason");
assertEquals(204, response.getStatus());
verify(userService).deactivateUser("1", REALM, "reason");
}
@Test
void testDeactivateUserError() {
doThrow(new RuntimeException("Deactivate failed")).when(userService).deactivateUser("1", REALM, null);
Response response = userResource.deactivateUser("1", REALM, null);
assertEquals(500, response.getStatus());
}
@Test
void testResetPassword() {
doNothing().when(userService).resetPassword("1", REALM, "newpassword", true);
UserResource.PasswordResetRequest request = new UserResource.PasswordResetRequest();
request.password = "newpassword";
request.temporary = true;
Response response = userResource.resetPassword("1", REALM, request);
assertEquals(204, response.getStatus());
verify(userService).resetPassword("1", REALM, "newpassword", true);
}
@Test
void testResetPasswordError() {
doThrow(new RuntimeException("Reset failed")).when(userService).resetPassword(any(), any(), any(),
anyBoolean());
UserResource.PasswordResetRequest request = new UserResource.PasswordResetRequest();
request.password = "newpassword";
Response response = userResource.resetPassword("1", REALM, request);
assertEquals(500, response.getStatus());
}
@Test
void testSendVerificationEmail() {
doNothing().when(userService).sendVerificationEmail("1", REALM);
Response response = userResource.sendVerificationEmail("1", REALM);
assertEquals(204, response.getStatus());
verify(userService).sendVerificationEmail("1", REALM);
}
@Test
void testSendVerificationEmailError() {
doThrow(new RuntimeException("Email failed")).when(userService).sendVerificationEmail("1", REALM);
Response response = userResource.sendVerificationEmail("1", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testLogoutAllSessions() {
when(userService.logoutAllSessions("1", REALM)).thenReturn(5);
Response response = userResource.logoutAllSessions("1", REALM);
assertEquals(200, response.getStatus());
assertNotNull(response.getEntity());
}
@Test
void testLogoutAllSessionsError() {
when(userService.logoutAllSessions("1", REALM)).thenThrow(new RuntimeException("Logout failed"));
Response response = userResource.logoutAllSessions("1", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testGetActiveSessions() {
when(userService.getActiveSessions("1", REALM)).thenReturn(Collections.emptyList());
Response response = userResource.getActiveSessions("1", REALM);
assertEquals(200, response.getStatus());
}
@Test
void testGetActiveSessionsError() {
when(userService.getActiveSessions("1", REALM)).thenThrow(new RuntimeException("Sessions failed"));
Response response = userResource.getActiveSessions("1", REALM);
assertEquals(500, response.getStatus());
}
@Test
void testPasswordResetRequestClass() {
UserResource.PasswordResetRequest request = new UserResource.PasswordResetRequest();
request.password = "password123";
request.temporary = false;
assertEquals("password123", request.password);
assertFalse(request.temporary);
}
@Test
void testSessionsRevokedResponseClass() {
UserResource.SessionsRevokedResponse response = new UserResource.SessionsRevokedResponse(5);
assertEquals(5, response.count);
}
@Test
void testErrorResponseClass() {
UserResource.ErrorResponse response = new UserResource.ErrorResponse("Error message");
assertEquals("Error message", response.message);
}
}

View File

@@ -0,0 +1,88 @@
package dev.lions.user.manager.security;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.core.SecurityContext;
import jakarta.ws.rs.core.UriInfo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.lang.reflect.Field;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
/**
* Tests unitaires pour DevSecurityContextProducer
*/
@ExtendWith(MockitoExtension.class)
class DevSecurityContextProducerTest {
@Mock
private ContainerRequestContext requestContext;
@Mock
private UriInfo uriInfo;
@Mock
private SecurityContext originalSecurityContext;
private DevSecurityContextProducer producer;
@BeforeEach
void setUp() throws Exception {
producer = new DevSecurityContextProducer();
// Injecter les propriétés via reflection
setField("profile", "dev");
setField("oidcEnabled", false);
}
private void setField(String fieldName, Object value) throws Exception {
Field field = DevSecurityContextProducer.class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(producer, value);
}
@Test
void testFilter_DevMode() throws Exception {
setField("profile", "dev");
setField("oidcEnabled", true);
when(requestContext.getUriInfo()).thenReturn(uriInfo);
when(uriInfo.getPath()).thenReturn("/api/users");
when(requestContext.getSecurityContext()).thenReturn(originalSecurityContext);
producer.filter(requestContext);
verify(requestContext, times(1)).setSecurityContext(any(SecurityContext.class));
}
@Test
void testFilter_ProdMode() throws Exception {
setField("profile", "prod");
setField("oidcEnabled", true);
// En mode prod, on n'a pas besoin de mocker getUriInfo car le code ne l'utilise pas
producer.filter(requestContext);
verify(requestContext, never()).setSecurityContext(any(SecurityContext.class));
}
@Test
void testFilter_OidcDisabled() throws Exception {
setField("profile", "prod");
setField("oidcEnabled", false);
when(requestContext.getUriInfo()).thenReturn(uriInfo);
when(uriInfo.getPath()).thenReturn("/api/users");
when(requestContext.getSecurityContext()).thenReturn(originalSecurityContext);
producer.filter(requestContext);
verify(requestContext, times(1)).setSecurityContext(any(SecurityContext.class));
}
}

View File

@@ -0,0 +1,151 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests supplémentaires pour AuditServiceImpl pour améliorer la couverture
*/
class AuditServiceImplAdditionalTest {
private AuditServiceImpl auditService;
@BeforeEach
void setUp() {
auditService = new AuditServiceImpl();
auditService.auditEnabled = true;
auditService.logToDatabase = false;
}
@Test
void testFindByActeur_WithDates() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "2", "user2", "realm1", "admin", "Updated");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> logs = auditService.findByActeur("admin", past, future, 0, 10);
assertNotNull(logs);
assertTrue(logs.size() > 0);
}
@Test
void testFindByRealm_WithDates() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> logs = auditService.findByRealm("realm1", past, future, 0, 10);
assertNotNull(logs);
}
@Test
void testFindByRessource() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> logs = auditService.findByRessource("USER", "1", past, future, 0, 10);
assertNotNull(logs);
}
@Test
void testCountByActionType() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "2", "user2", "realm1", "admin", "Created");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
java.util.Map<TypeActionAudit, Long> counts = auditService.countByActionType("realm1", past, future);
assertNotNull(counts);
assertTrue(counts.containsKey(TypeActionAudit.USER_CREATE));
}
@Test
void testCountByActeur() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "2", "user2", "realm1", "admin", "Updated");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
java.util.Map<String, Long> counts = auditService.countByActeur("realm1", past, future);
assertNotNull(counts);
}
@Test
void testCountSuccessVsFailure() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logFailure(TypeActionAudit.USER_CREATE, "USER", "2", "user2", "realm1", "admin", "Failed", "Error");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
java.util.Map<String, Long> result = auditService.countSuccessVsFailure("realm1", past, future);
assertNotNull(result);
assertTrue(result.containsKey("success"));
assertTrue(result.containsKey("failure"));
}
@Test
void testExportToCSV() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
String csv = auditService.exportToCSV("realm1", past, future);
assertNotNull(csv);
assertTrue(csv.length() > 0);
}
@Test
void testPurgeOldLogs() {
// Créer des logs anciens
for (int i = 0; i < 10; i++) {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", String.valueOf(i),
"user" + i, "realm1", "admin", "Created");
}
LocalDateTime cutoffDate = LocalDateTime.now().minusDays(30);
long purged = auditService.purgeOldLogs(cutoffDate);
assertTrue(purged >= 0);
}
@Test
void testGetTotalCount() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "2", "user2", "realm1", "admin", "Updated");
long total = auditService.getTotalCount();
assertEquals(2, total);
}
}

View File

@@ -0,0 +1,322 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests complets pour AuditServiceImpl pour atteindre 100% de couverture
* Couvre les branches manquantes : auditEnabled=false, acteurUsername="*", dates null, etc.
*/
class AuditServiceImplCompleteTest {
private AuditServiceImpl auditService;
@BeforeEach
void setUp() {
auditService = new AuditServiceImpl();
auditService.auditEnabled = true;
auditService.logToDatabase = false;
}
@Test
void testLogAction_AuditDisabled() {
auditService.auditEnabled = false;
AuditLogDTO auditLog = AuditLogDTO.builder()
.typeAction(TypeActionAudit.USER_CREATE)
.acteurUsername("admin")
.build();
AuditLogDTO result = auditService.logAction(auditLog);
assertEquals(auditLog, result);
}
@Test
void testLogAction_WithId() {
AuditLogDTO auditLog = AuditLogDTO.builder()
.id("custom-id")
.typeAction(TypeActionAudit.USER_CREATE)
.acteurUsername("admin")
.build();
AuditLogDTO result = auditService.logAction(auditLog);
assertEquals("custom-id", result.getId());
}
@Test
void testLogAction_WithDateAction() {
LocalDateTime customDate = LocalDateTime.now().minusDays(1);
AuditLogDTO auditLog = AuditLogDTO.builder()
.typeAction(TypeActionAudit.USER_CREATE)
.acteurUsername("admin")
.dateAction(customDate)
.build();
AuditLogDTO result = auditService.logAction(auditLog);
assertEquals(customDate, result.getDateAction());
}
@Test
void testSearchLogs_WithWildcardActeur() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "2", "user2", "realm1", "user2", "Updated");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
// Test avec acteurUsername = "*" (wildcard)
List<AuditLogDTO> logs = auditService.findByActeur("*", past, future, 0, 10);
assertNotNull(logs);
assertTrue(logs.size() >= 2);
}
@Test
void testSearchLogs_WithNullDates() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
// Test avec dates null
List<AuditLogDTO> logs = auditService.findByActeur("admin", null, null, 0, 10);
assertNotNull(logs);
assertTrue(logs.size() > 0);
}
@Test
void testSearchLogs_WithNullTypeAction() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "2", "user2", "realm1", "admin", "Updated");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
// Test avec typeAction null (via findByRealm qui ne filtre pas par typeAction)
List<AuditLogDTO> logs = auditService.findByRealm("realm1", past, future, 0, 10);
assertNotNull(logs);
}
@Test
void testSearchLogs_WithNullRessourceType() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
// Test avec ressourceType null (via findByRealm)
List<AuditLogDTO> logs = auditService.findByRealm("realm1", past, future, 0, 10);
assertNotNull(logs);
}
@Test
void testFindFailures() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logFailure(TypeActionAudit.USER_CREATE, "USER", "2", "user2", "realm1", "admin", "Failed", "Error");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> failures = auditService.findFailures("realm1", past, future, 0, 10);
assertNotNull(failures);
assertTrue(failures.size() > 0);
assertFalse(failures.get(0).isSuccessful());
}
@Test
void testFindCriticalActions_UserDelete() {
auditService.logSuccess(TypeActionAudit.USER_DELETE, "USER", "1", "user1", "realm1", "admin", "Deleted");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> critical = auditService.findCriticalActions("realm1", past, future, 0, 10);
assertNotNull(critical);
assertTrue(critical.size() > 0);
assertEquals(TypeActionAudit.USER_DELETE, critical.get(0).getTypeAction());
}
@Test
void testFindCriticalActions_RoleDelete() {
auditService.logSuccess(TypeActionAudit.ROLE_DELETE, "ROLE", "1", "role1", "realm1", "admin", "Deleted");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> critical = auditService.findCriticalActions("realm1", past, future, 0, 10);
assertNotNull(critical);
assertTrue(critical.size() > 0);
assertEquals(TypeActionAudit.ROLE_DELETE, critical.get(0).getTypeAction());
}
@Test
void testFindCriticalActions_SessionRevokeAll() {
auditService.logSuccess(TypeActionAudit.SESSION_REVOKE_ALL, "SESSION", "1", "session1", "realm1", "admin", "Revoked");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> critical = auditService.findCriticalActions("realm1", past, future, 0, 10);
assertNotNull(critical);
assertTrue(critical.size() > 0);
assertEquals(TypeActionAudit.SESSION_REVOKE_ALL, critical.get(0).getTypeAction());
}
@Test
void testFindCriticalActions_WithDateFilters() {
LocalDateTime oldDate = LocalDateTime.now().minusDays(10);
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
// Créer un log ancien (hors de la plage)
AuditLogDTO oldLog = AuditLogDTO.builder()
.typeAction(TypeActionAudit.USER_DELETE)
.acteurUsername("admin")
.dateAction(oldDate)
.build();
auditService.logAction(oldLog);
// Créer un log récent (dans la plage)
auditService.logSuccess(TypeActionAudit.USER_DELETE, "USER", "2", "user2", "realm1", "admin", "Deleted");
List<AuditLogDTO> critical = auditService.findCriticalActions("realm1", past, future, 0, 10);
assertNotNull(critical);
// Seul le log récent devrait être retourné
assertTrue(critical.size() >= 1);
}
@Test
void testGetAuditStatistics() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logFailure(TypeActionAudit.USER_CREATE, "USER", "2", "user2", "realm1", "admin", "Failed", "Error");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
Map<String, Object> stats = auditService.getAuditStatistics("realm1", past, future);
assertNotNull(stats);
assertTrue(stats.containsKey("total"));
assertTrue(stats.containsKey("success"));
assertTrue(stats.containsKey("failure"));
assertTrue(stats.containsKey("byActionType"));
assertTrue(stats.containsKey("byActeur"));
}
@Test
void testExportToCSV_WithNullValues() {
AuditLogDTO auditLog = AuditLogDTO.builder()
.typeAction(TypeActionAudit.USER_CREATE)
.acteurUsername("admin")
.ressourceType("USER")
.ressourceId("1")
.success(true)
.ipAddress(null)
.description(null)
.errorMessage(null)
.build();
auditService.logAction(auditLog);
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
String csv = auditService.exportToCSV("realm1", past, future);
assertNotNull(csv);
assertTrue(csv.contains("admin"));
}
@Test
void testExportToCSV_WithQuotesInDescription() {
AuditLogDTO auditLog = AuditLogDTO.builder()
.typeAction(TypeActionAudit.USER_CREATE)
.acteurUsername("admin")
.ressourceType("USER")
.ressourceId("1")
.success(true)
.description("Test \"quoted\" description")
.errorMessage("Error \"message\"")
.build();
auditService.logAction(auditLog);
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
String csv = auditService.exportToCSV("realm1", past, future);
assertNotNull(csv);
// Les guillemets devraient être échappés
assertTrue(csv.contains("\"\""));
}
@Test
void testClearAll() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
assertEquals(1, auditService.getTotalCount());
auditService.clearAll();
assertEquals(0, auditService.getTotalCount());
}
@Test
void testFindByTypeAction() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "2", "user2", "realm1", "admin", "Updated");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
List<AuditLogDTO> logs = auditService.findByTypeAction(TypeActionAudit.USER_CREATE, "realm1", past, future, 0, 10);
assertNotNull(logs);
assertTrue(logs.size() > 0);
assertEquals(TypeActionAudit.USER_CREATE, logs.get(0).getTypeAction());
}
@Test
void testSearchLogs_WithNullSuccess() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm1", "admin", "Created");
auditService.logFailure(TypeActionAudit.USER_CREATE, "USER", "2", "user2", "realm1", "admin", "Failed", "Error");
LocalDateTime now = LocalDateTime.now();
LocalDateTime past = now.minusDays(1);
LocalDateTime future = now.plusDays(1);
// findByRealm ne filtre pas par success, donc success = null
List<AuditLogDTO> logs = auditService.findByRealm("realm1", past, future, 0, 10);
assertNotNull(logs);
assertTrue(logs.size() >= 2);
}
}

View File

@@ -0,0 +1,78 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.dto.audit.AuditLogDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class AuditServiceImplTest {
AuditServiceImpl auditService;
@BeforeEach
void setUp() {
auditService = new AuditServiceImpl();
auditService.auditEnabled = true; // manually injecting config property
auditService.logToDatabase = false;
}
@Test
void testLogAction() {
AuditLogDTO log = new AuditLogDTO();
log.setTypeAction(TypeActionAudit.USER_CREATE);
log.setActeurUsername("admin");
auditService.logAction(log);
assertEquals(1, auditService.getTotalCount());
assertNotNull(log.getId());
assertNotNull(log.getDateAction());
}
@Test
void testLogDisabled() {
auditService.auditEnabled = false;
AuditLogDTO log = new AuditLogDTO();
auditService.logAction(log);
assertEquals(0, auditService.getTotalCount());
}
@Test
void testLogSuccess() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user", "realm", "admin", "desc");
assertEquals(1, auditService.getTotalCount());
}
@Test
void testLogFailure() {
auditService.logFailure(TypeActionAudit.USER_CREATE, "USER", "1", "user", "realm", "admin", "ERR", "Error");
assertEquals(1, auditService.getTotalCount());
List<AuditLogDTO> failures = auditService.findFailures("realm", null, null, 0, 10);
assertEquals(1, failures.size());
}
@Test
void testSearchLogs() {
auditService.logSuccess(TypeActionAudit.USER_CREATE, "USER", "1", "user1", "realm", "admin1", "");
auditService.logSuccess(TypeActionAudit.USER_UPDATE, "USER", "1", "user1", "realm", "admin1", "");
auditService.logSuccess(TypeActionAudit.ROLE_CREATE, "ROLE", "r", "role", "realm", "admin2", "");
List<AuditLogDTO> byActeur = auditService.findByActeur("admin1", null, null, 0, 10);
assertEquals(2, byActeur.size());
List<AuditLogDTO> byType = auditService.findByTypeAction(TypeActionAudit.ROLE_CREATE, "realm", null, null, 0,
10);
assertEquals(1, byType.size());
}
@Test
void testClearAll() {
auditService.logAction(new AuditLogDTO());
auditService.clearAll();
assertEquals(0, auditService.getTotalCount());
}
}

View File

@@ -0,0 +1,280 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.dto.realm.RealmAssignmentDTO;
import dev.lions.user.manager.enums.audit.TypeActionAudit;
import dev.lions.user.manager.service.AuditService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests unitaires pour RealmAuthorizationServiceImpl
*/
@ExtendWith(MockitoExtension.class)
class RealmAuthorizationServiceImplTest {
@Mock
private AuditService auditService;
@InjectMocks
private RealmAuthorizationServiceImpl realmAuthorizationService;
private RealmAssignmentDTO assignment;
@BeforeEach
void setUp() {
assignment = RealmAssignmentDTO.builder()
.id("assignment-1")
.userId("user-1")
.username("testuser")
.email("test@example.com")
.realmName("realm1")
.isSuperAdmin(false)
.active(true)
.assignedAt(LocalDateTime.now())
.assignedBy("admin")
.build();
}
@Test
void testGetAllAssignments_Empty() {
List<RealmAssignmentDTO> assignments = realmAuthorizationService.getAllAssignments();
assertTrue(assignments.isEmpty());
}
@Test
void testGetAllAssignments_WithAssignments() {
realmAuthorizationService.assignRealmToUser(assignment);
List<RealmAssignmentDTO> assignments = realmAuthorizationService.getAllAssignments();
assertEquals(1, assignments.size());
assertEquals("assignment-1", assignments.get(0).getId());
}
@Test
void testGetAssignmentsByUser_Success() {
realmAuthorizationService.assignRealmToUser(assignment);
List<RealmAssignmentDTO> assignments = realmAuthorizationService.getAssignmentsByUser("user-1");
assertEquals(1, assignments.size());
}
@Test
void testGetAssignmentsByUser_Empty() {
List<RealmAssignmentDTO> assignments = realmAuthorizationService.getAssignmentsByUser("user-1");
assertTrue(assignments.isEmpty());
}
@Test
void testGetAssignmentsByRealm_Success() {
realmAuthorizationService.assignRealmToUser(assignment);
List<RealmAssignmentDTO> assignments = realmAuthorizationService.getAssignmentsByRealm("realm1");
assertEquals(1, assignments.size());
}
@Test
void testGetAssignmentById_Success() {
realmAuthorizationService.assignRealmToUser(assignment);
Optional<RealmAssignmentDTO> found = realmAuthorizationService.getAssignmentById("assignment-1");
assertTrue(found.isPresent());
assertEquals("assignment-1", found.get().getId());
}
@Test
void testGetAssignmentById_NotFound() {
Optional<RealmAssignmentDTO> found = realmAuthorizationService.getAssignmentById("non-existent");
assertFalse(found.isPresent());
}
@Test
void testCanManageRealm_SuperAdmin() {
realmAuthorizationService.setSuperAdmin("user-1", true);
assertTrue(realmAuthorizationService.canManageRealm("user-1", "any-realm"));
}
@Test
void testCanManageRealm_WithAssignment() {
realmAuthorizationService.assignRealmToUser(assignment);
assertTrue(realmAuthorizationService.canManageRealm("user-1", "realm1"));
}
@Test
void testCanManageRealm_NoAccess() {
assertFalse(realmAuthorizationService.canManageRealm("user-1", "realm1"));
}
@Test
void testIsSuperAdmin_True() {
realmAuthorizationService.setSuperAdmin("user-1", true);
assertTrue(realmAuthorizationService.isSuperAdmin("user-1"));
}
@Test
void testIsSuperAdmin_False() {
assertFalse(realmAuthorizationService.isSuperAdmin("user-1"));
}
@Test
void testGetAuthorizedRealms_SuperAdmin() {
realmAuthorizationService.setSuperAdmin("user-1", true);
List<String> realms = realmAuthorizationService.getAuthorizedRealms("user-1");
assertTrue(realms.isEmpty()); // Super admin retourne liste vide
}
@Test
void testGetAuthorizedRealms_WithAssignments() {
realmAuthorizationService.assignRealmToUser(assignment);
List<String> realms = realmAuthorizationService.getAuthorizedRealms("user-1");
assertEquals(1, realms.size());
assertEquals("realm1", realms.get(0));
}
@Test
void testAssignRealmToUser_Success() {
doNothing().when(auditService).logSuccess(
any(TypeActionAudit.class),
anyString(),
anyString(),
anyString(),
anyString(),
anyString(),
anyString()
);
RealmAssignmentDTO result = realmAuthorizationService.assignRealmToUser(assignment);
assertNotNull(result);
assertNotNull(result.getId());
assertTrue(result.isActive());
assertNotNull(result.getAssignedAt());
}
@Test
void testAssignRealmToUser_NoUserId() {
assignment.setUserId(null);
assertThrows(IllegalArgumentException.class, () -> {
realmAuthorizationService.assignRealmToUser(assignment);
});
}
@Test
void testAssignRealmToUser_NoRealmName() {
assignment.setRealmName(null);
assertThrows(IllegalArgumentException.class, () -> {
realmAuthorizationService.assignRealmToUser(assignment);
});
}
@Test
void testAssignRealmToUser_Duplicate() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
assertThrows(IllegalArgumentException.class, () -> {
realmAuthorizationService.assignRealmToUser(assignment);
});
}
@Test
void testRevokeRealmFromUser_Success() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
realmAuthorizationService.revokeRealmFromUser("user-1", "realm1");
assertFalse(realmAuthorizationService.canManageRealm("user-1", "realm1"));
}
@Test
void testRevokeRealmFromUser_NotExists() {
// Ne doit pas lever d'exception si l'assignation n'existe pas
assertDoesNotThrow(() -> {
realmAuthorizationService.revokeRealmFromUser("user-1", "realm1");
});
}
@Test
void testRevokeAllRealmsFromUser() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
realmAuthorizationService.revokeAllRealmsFromUser("user-1");
assertTrue(realmAuthorizationService.getAssignmentsByUser("user-1").isEmpty());
}
@Test
void testSetSuperAdmin_True() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.setSuperAdmin("user-1", true);
assertTrue(realmAuthorizationService.isSuperAdmin("user-1"));
}
@Test
void testSetSuperAdmin_False() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.setSuperAdmin("user-1", true);
realmAuthorizationService.setSuperAdmin("user-1", false);
assertFalse(realmAuthorizationService.isSuperAdmin("user-1"));
}
@Test
void testDeactivateAssignment_Success() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
realmAuthorizationService.deactivateAssignment(assignment.getId());
Optional<RealmAssignmentDTO> found = realmAuthorizationService.getAssignmentById(assignment.getId());
assertTrue(found.isPresent());
assertFalse(found.get().isActive());
}
@Test
void testDeactivateAssignment_NotFound() {
assertThrows(IllegalArgumentException.class, () -> {
realmAuthorizationService.deactivateAssignment("non-existent");
});
}
@Test
void testActivateAssignment_Success() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
realmAuthorizationService.deactivateAssignment(assignment.getId());
realmAuthorizationService.activateAssignment(assignment.getId());
Optional<RealmAssignmentDTO> found = realmAuthorizationService.getAssignmentById(assignment.getId());
assertTrue(found.isPresent());
assertTrue(found.get().isActive());
}
@Test
void testCountAssignmentsByUser() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
long count = realmAuthorizationService.countAssignmentsByUser("user-1");
assertEquals(1, count);
}
@Test
void testCountUsersByRealm() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
long count = realmAuthorizationService.countUsersByRealm("realm1");
assertEquals(1, count);
}
@Test
void testAssignmentExists_True() {
doNothing().when(auditService).logSuccess(any(), anyString(), anyString(), anyString(), anyString(), anyString(), anyString());
realmAuthorizationService.assignRealmToUser(assignment);
assertTrue(realmAuthorizationService.assignmentExists("user-1", "realm1"));
}
@Test
void testAssignmentExists_False() {
assertFalse(realmAuthorizationService.assignmentExists("user-1", "realm1"));
}
}

View File

@@ -0,0 +1,350 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import dev.lions.user.manager.mapper.RoleMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.*;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests complets pour RoleServiceImpl pour atteindre 100% de couverture
* Couvre updateRole, deleteRole pour CLIENT_ROLE, createRealmRole avec rôle existant, etc.
*/
@ExtendWith(MockitoExtension.class)
class RoleServiceImplCompleteTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private Keycloak keycloakInstance;
@Mock
private RealmResource realmResource;
@Mock
private RolesResource rolesResource;
@Mock
private RoleResource roleResource;
@Mock
private ClientsResource clientsResource;
@Mock
private ClientResource clientResource;
@InjectMocks
private RoleServiceImpl roleService;
private static final String REALM = "test-realm";
private static final String ROLE_ID = "role-123";
private static final String ROLE_NAME = "test-role";
private static final String CLIENT_NAME = "test-client";
private static final String INTERNAL_CLIENT_ID = "internal-client-id";
@Test
void testCreateRealmRole_RoleAlreadyExists() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
RoleRepresentation existingRole = new RoleRepresentation();
existingRole.setName(ROLE_NAME);
when(roleResource.toRepresentation()).thenReturn(existingRole);
RoleDTO roleDTO = RoleDTO.builder()
.name(ROLE_NAME)
.description("Test role")
.build();
assertThrows(IllegalArgumentException.class, () ->
roleService.createRealmRole(roleDTO, REALM));
}
@Test
void testUpdateRole_RealmRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
// Mock getRealmRoleById
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId(ROLE_ID);
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.description("Updated description")
.build();
RoleDTO result = roleService.updateRole(ROLE_ID, roleDTO, REALM, TypeRole.REALM_ROLE, null);
assertNotNull(result);
verify(roleResource).update(any(RoleRepresentation.class));
}
@Test
void testUpdateRole_RealmRole_NotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.build();
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.updateRole(ROLE_ID, roleDTO, REALM, TypeRole.REALM_ROLE, null));
}
@Test
void testUpdateRole_RealmRole_NoDescription() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId(ROLE_ID);
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.description(null) // No description
.build();
RoleDTO result = roleService.updateRole(ROLE_ID, roleDTO, REALM, TypeRole.REALM_ROLE, null);
assertNotNull(result);
verify(roleResource).update(any(RoleRepresentation.class));
}
@Test
void testUpdateRole_ClientRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation client = new ClientRepresentation();
client.setId(INTERNAL_CLIENT_ID);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get(INTERNAL_CLIENT_ID)).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
// Mock getRoleById
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId(ROLE_ID);
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.description("Updated description")
.build();
RoleDTO result = roleService.updateRole(ROLE_ID, roleDTO, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME);
assertNotNull(result);
assertEquals(CLIENT_NAME, result.getClientId());
verify(roleResource).update(any(RoleRepresentation.class));
}
@Test
void testUpdateRole_ClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.build();
// getRoleById is called first, which will throw NotFoundException when client is not found
// Actually, getRoleById returns Optional.empty() when client is not found
// So it will throw NotFoundException for role not found
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.updateRole(ROLE_ID, roleDTO, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME));
}
@Test
void testUpdateRole_ClientRole_NotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation client = new ClientRepresentation();
client.setId(INTERNAL_CLIENT_ID);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get(INTERNAL_CLIENT_ID)).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.build();
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.updateRole(ROLE_ID, roleDTO, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME));
}
@Test
void testUpdateRole_UnsupportedType() {
RoleDTO roleDTO = RoleDTO.builder()
.id(ROLE_ID)
.name(ROLE_NAME)
.build();
assertThrows(IllegalArgumentException.class, () ->
roleService.updateRole(ROLE_ID, roleDTO, REALM, null, null));
}
@Test
void testDeleteRole_ClientRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation client = new ClientRepresentation();
client.setId(INTERNAL_CLIENT_ID);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get(INTERNAL_CLIENT_ID)).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
// Mock getRoleById - getRoleById for CLIENT_ROLE only uses rolesResource.list()
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId(ROLE_ID);
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
roleService.deleteRole(ROLE_ID, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME);
verify(rolesResource).deleteRole(ROLE_NAME);
}
@Test
void testDeleteRole_ClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
// getRoleById is called first, which returns Optional.empty() when client is not found
// So it will throw NotFoundException for role not found
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.deleteRole(ROLE_ID, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME));
}
@Test
void testDeleteRole_ClientRole_NotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation client = new ClientRepresentation();
client.setId(INTERNAL_CLIENT_ID);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get(INTERNAL_CLIENT_ID)).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.deleteRole(ROLE_ID, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME));
}
@Test
void testDeleteRole_UnsupportedType() {
assertThrows(IllegalArgumentException.class, () ->
roleService.deleteRole(ROLE_ID, REALM, null, null));
}
// Note: getRealmRoleById is private, so we test it indirectly through updateRole
// The exception path is tested via updateRole_RealmRole_NotFound
@Test
void testGetAllRealmRoles_Success() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
RoleRepresentation role1 = new RoleRepresentation();
role1.setName("role1");
RoleRepresentation role2 = new RoleRepresentation();
role2.setName("role2");
when(rolesResource.list()).thenReturn(List.of(role1, role2));
var result = roleService.getAllRealmRoles(REALM);
assertNotNull(result);
assertEquals(2, result.size());
}
@Test
void testGetAllRealmRoles_With404InMessage() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Server response is: 404"));
assertThrows(IllegalArgumentException.class, () ->
roleService.getAllRealmRoles(REALM));
}
@Test
void testGetAllRealmRoles_WithNotInMessage() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Not Found"));
assertThrows(IllegalArgumentException.class, () ->
roleService.getAllRealmRoles(REALM));
}
@Test
void testGetAllRealmRoles_WithOtherException() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () ->
roleService.getAllRealmRoles(REALM));
}
}

View File

@@ -0,0 +1,245 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.*;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests supplémentaires pour RoleServiceImpl pour améliorer la couverture
* Couvre les méthodes : userHasRole, roleExists, countUsersWithRole
*/
@ExtendWith(MockitoExtension.class)
class RoleServiceImplExtendedTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private Keycloak keycloakInstance;
@Mock
private RealmResource realmResource;
@Mock
private RolesResource rolesResource;
@Mock
private RoleResource roleResource;
@Mock
private UsersResource usersResource;
@Mock
private UserResource userResource;
@Mock
private RoleMappingResource roleMappingResource;
@Mock
private RoleScopeResource realmLevelRoleScopeResource;
@Mock
private RoleScopeResource clientLevelRoleScopeResource;
@Mock
private ClientsResource clientsResource;
@InjectMocks
private RoleServiceImpl roleService;
private static final String REALM = "test-realm";
private static final String USER_ID = "user-123";
private static final String ROLE_NAME = "admin";
private static final String CLIENT_NAME = "test-client";
@Test
void testUserHasRole_RealmRole_True() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(realmLevelRoleScopeResource);
RoleRepresentation role = new RoleRepresentation();
role.setName(ROLE_NAME);
when(realmLevelRoleScopeResource.listEffective()).thenReturn(List.of(role));
boolean result = roleService.userHasRole(USER_ID, ROLE_NAME, REALM, TypeRole.REALM_ROLE, null);
assertTrue(result);
}
@Test
void testUserHasRole_RealmRole_False() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(realmLevelRoleScopeResource);
when(realmLevelRoleScopeResource.listEffective()).thenReturn(Collections.emptyList());
boolean result = roleService.userHasRole(USER_ID, ROLE_NAME, REALM, TypeRole.REALM_ROLE, null);
assertFalse(result);
}
@Test
void testUserHasRole_ClientRole_True() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
ClientRepresentation client = new ClientRepresentation();
client.setId("client-123");
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(roleMappingResource.clientLevel("client-123")).thenReturn(clientLevelRoleScopeResource);
RoleRepresentation role = new RoleRepresentation();
role.setName(ROLE_NAME);
when(clientLevelRoleScopeResource.listEffective()).thenReturn(List.of(role));
boolean result = roleService.userHasRole(USER_ID, ROLE_NAME, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME);
assertTrue(result);
}
@Test
void testUserHasRole_ClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
boolean result = roleService.userHasRole(USER_ID, ROLE_NAME, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME);
assertFalse(result);
}
@Test
void testUserHasRole_ClientRole_NullClientName() {
boolean result = roleService.userHasRole(USER_ID, ROLE_NAME, REALM, TypeRole.CLIENT_ROLE, null);
assertFalse(result);
}
@Test
void testRoleExists_RealmRole_True() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
RoleRepresentation role = new RoleRepresentation();
role.setName(ROLE_NAME);
when(roleResource.toRepresentation()).thenReturn(role);
boolean result = roleService.roleExists(ROLE_NAME, REALM, TypeRole.REALM_ROLE, null);
assertTrue(result);
}
@Test
void testRoleExists_RealmRole_False() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenThrow(new jakarta.ws.rs.NotFoundException());
boolean result = roleService.roleExists(ROLE_NAME, REALM, TypeRole.REALM_ROLE, null);
assertFalse(result);
}
@Test
void testCountUsersWithRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.users()).thenReturn(usersResource);
// Mock getRoleById
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId("role-123");
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
// Mock user list
UserRepresentation user1 = new UserRepresentation();
user1.setId("user-1");
UserRepresentation user2 = new UserRepresentation();
user2.setId("user-2");
when(usersResource.list()).thenReturn(List.of(user1, user2));
// Mock userHasRole for each user
when(usersResource.get("user-1")).thenReturn(userResource);
when(usersResource.get("user-2")).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(realmLevelRoleScopeResource);
RoleRepresentation role = new RoleRepresentation();
role.setName(ROLE_NAME);
// User 1 has role, user 2 doesn't
when(realmLevelRoleScopeResource.listEffective())
.thenReturn(List.of(role)) // user-1
.thenReturn(Collections.emptyList()); // user-2
long count = roleService.countUsersWithRole("role-123", REALM, TypeRole.REALM_ROLE, null);
assertEquals(1, count);
}
@Test
void testCountUsersWithRole_RoleNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
long count = roleService.countUsersWithRole("non-existent-role", REALM, TypeRole.REALM_ROLE, null);
assertEquals(0, count);
}
@Test
void testCountUsersWithRole_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.users()).thenReturn(usersResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId("role-123");
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
when(usersResource.list()).thenThrow(new RuntimeException("Error"));
long count = roleService.countUsersWithRole("role-123", REALM, TypeRole.REALM_ROLE, null);
assertEquals(0, count);
}
}

View File

@@ -0,0 +1,589 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.role.RoleAssignmentDTO;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.*;
import org.keycloak.representations.idm.ClientRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests d'intégration pour RoleServiceImpl - Cas limites et branches conditionnelles complexes
*/
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class RoleServiceImplIntegrationTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private Keycloak keycloakInstance;
@Mock
private RealmResource realmResource;
@Mock
private RolesResource rolesResource;
@Mock
private RoleResource roleResource;
@Mock
private UsersResource usersResource;
@Mock
private UserResource userResource;
@Mock
private RoleMappingResource roleMappingResource;
@Mock
private RoleScopeResource roleScopeResource;
@Mock
private ClientsResource clientsResource;
@Mock
private ClientResource clientResource;
@InjectMocks
private RoleServiceImpl roleService;
private static final String REALM = "test-realm";
private static final String USER_ID = "user-123";
private static final String ROLE_NAME = "admin";
private static final String CLIENT_NAME = "test-client";
private static final String ROLE_ID = "role-123";
// ==================== Tests getRoleByName - Cas limites ====================
@Test
void testGetRoleByName_RealmRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName(ROLE_NAME);
roleRep.setId(ROLE_ID);
when(roleResource.toRepresentation()).thenReturn(roleRep);
Optional<RoleDTO> result = roleService.getRoleByName(ROLE_NAME, REALM, TypeRole.REALM_ROLE, null);
assertTrue(result.isPresent());
assertEquals(ROLE_NAME, result.get().getName());
}
@Test
void testGetRoleByName_RealmRole_NotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenThrow(new jakarta.ws.rs.NotFoundException());
Optional<RoleDTO> result = roleService.getRoleByName(ROLE_NAME, REALM, TypeRole.REALM_ROLE, null);
assertFalse(result.isPresent());
}
@Test
void testGetRoleByName_ClientRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation client = new ClientRepresentation();
client.setId("client-123");
client.setClientId(CLIENT_NAME);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get("client-123")).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName(ROLE_NAME);
roleRep.setId(ROLE_ID);
when(roleResource.toRepresentation()).thenReturn(roleRep);
Optional<RoleDTO> result = roleService.getRoleByName(ROLE_NAME, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME);
assertTrue(result.isPresent());
assertEquals(ROLE_NAME, result.get().getName());
}
@Test
void testGetRoleByName_ClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
Optional<RoleDTO> result = roleService.getRoleByName(ROLE_NAME, REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME);
assertFalse(result.isPresent());
}
@Test
void testGetRoleByName_ClientRole_NullClientName() {
Optional<RoleDTO> result = roleService.getRoleByName(ROLE_NAME, REALM, TypeRole.CLIENT_ROLE, null);
assertFalse(result.isPresent());
}
// ==================== Tests assignRolesToUser - Cas limites ====================
@Test
void testAssignRolesToUser_RealmRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(roleScopeResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName(ROLE_NAME);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
.userId(USER_ID)
.realmName(REALM)
.typeRole(TypeRole.REALM_ROLE)
.roleNames(List.of(ROLE_NAME))
.build();
roleService.assignRolesToUser(assignment);
verify(roleScopeResource).add(anyList());
}
@Test
void testAssignRolesToUser_ClientRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
ClientRepresentation client = new ClientRepresentation();
client.setId("client-123");
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get("client-123")).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleMappingResource.clientLevel("client-123")).thenReturn(roleScopeResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName(ROLE_NAME);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
.userId(USER_ID)
.realmName(REALM)
.typeRole(TypeRole.CLIENT_ROLE)
.clientName(CLIENT_NAME)
.roleNames(List.of(ROLE_NAME))
.build();
roleService.assignRolesToUser(assignment);
verify(roleScopeResource).add(anyList());
}
@Test
void testAssignRolesToUser_ClientRole_NullClientName() {
RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
.userId(USER_ID)
.realmName(REALM)
.typeRole(TypeRole.CLIENT_ROLE)
.clientName(null)
.roleNames(List.of(ROLE_NAME))
.build();
assertThrows(IllegalArgumentException.class, () -> roleService.assignRolesToUser(assignment));
}
// ==================== Tests revokeRolesFromUser - Cas limites ====================
@Test
void testRevokeRolesFromUser_RealmRole_Success() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(roleScopeResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName(ROLE_NAME);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
.userId(USER_ID)
.realmName(REALM)
.typeRole(TypeRole.REALM_ROLE)
.roleNames(List.of(ROLE_NAME))
.build();
roleService.revokeRolesFromUser(assignment);
verify(roleScopeResource).remove(anyList());
}
@Test
void testRevokeRolesFromUser_ClientRole_NullClientName() {
RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
.userId(USER_ID)
.realmName(REALM)
.typeRole(TypeRole.CLIENT_ROLE)
.clientName(null)
.roleNames(List.of(ROLE_NAME))
.build();
assertThrows(IllegalArgumentException.class, () -> roleService.revokeRolesFromUser(assignment));
}
// ==================== Tests getAllUserRoles - Cas limites ====================
@Test
void testGetAllUserRoles_WithRealmAndClientRoles() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(realmResource.clients()).thenReturn(clientsResource);
// Mock realm roles - getUserRealmRoles is called first
RoleScopeResource realmRoleScope = mock(RoleScopeResource.class);
RoleRepresentation realmRole = new RoleRepresentation();
realmRole.setName("realm-role");
when(roleMappingResource.realmLevel()).thenReturn(realmRoleScope);
when(realmRoleScope.listAll()).thenReturn(List.of(realmRole));
// Mock client roles - getAllUserRoles calls getUserClientRoles for each client
// getAllUserRoles calls getUserClientRoles with client.getClientId() (CLIENT_NAME)
// getUserClientRoles then finds the client by clientId and uses the internal ID
ClientRepresentation client = new ClientRepresentation();
client.setId("client-123"); // Internal ID
client.setClientId(CLIENT_NAME); // Client ID
when(clientsResource.findAll()).thenReturn(List.of(client));
// getUserClientRoles finds client by clientId
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
// getUserClientRoles uses internal ID for clientLevel
RoleScopeResource clientRoleScope = mock(RoleScopeResource.class);
when(roleMappingResource.clientLevel("client-123")).thenReturn(clientRoleScope);
RoleRepresentation clientRole = new RoleRepresentation();
clientRole.setName("client-role");
when(clientRoleScope.listAll()).thenReturn(List.of(clientRole));
List<RoleDTO> result = roleService.getAllUserRoles(USER_ID, REALM);
assertNotNull(result);
assertTrue(result.size() >= 1);
}
@Test
void testGetAllUserRoles_WithExceptionInClientRoles() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(roleScopeResource);
when(realmResource.clients()).thenReturn(clientsResource);
// Mock realm roles
RoleRepresentation realmRole = new RoleRepresentation();
realmRole.setName("realm-role");
when(roleScopeResource.listAll()).thenReturn(List.of(realmRole));
// Exception when getting clients
when(clientsResource.findAll()).thenThrow(new RuntimeException("Error"));
// Should not throw, just log warning
List<RoleDTO> result = roleService.getAllUserRoles(USER_ID, REALM);
assertNotNull(result);
assertEquals(1, result.size()); // Only realm roles
}
// ==================== Tests addCompositeRoles - Cas limites ====================
@Test
void testAddCompositeRoles_RealmRole_ParentNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
// getRoleById returns Optional.empty() when role not found, which causes NotFoundException
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.addCompositeRoles(ROLE_ID, List.of("child-1"), REALM, TypeRole.REALM_ROLE, null));
}
@Test
void testAddCompositeRoles_RealmRole_ChildNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
RoleRepresentation parentRole = new RoleRepresentation();
parentRole.setId(ROLE_ID);
parentRole.setName("parent");
// Mock getRoleById to return parent role
when(rolesResource.list()).thenReturn(List.of(parentRole));
when(rolesResource.get("parent")).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(parentRole);
// Child role not found - getRealmRoleById returns empty for child
// This means childRoleNames will be empty, so addComposites won't be called
// Should not throw, just log warning and skip
roleService.addCompositeRoles(ROLE_ID, List.of("child-id"), REALM, TypeRole.REALM_ROLE, null);
// Verify that get was called for parent role - use lenient to avoid unnecessary stubbing
verify(rolesResource, atLeastOnce()).list();
}
@Test
void testAddCompositeRoles_ClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.clients()).thenReturn(clientsResource);
// Mock getRoleById to return a role
RoleRepresentation parentRole = new RoleRepresentation();
parentRole.setId(ROLE_ID);
parentRole.setName("parent");
when(rolesResource.list()).thenReturn(List.of(parentRole));
when(rolesResource.get("parent")).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(parentRole);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
// When client not found, it throws IllegalArgumentException in removeCompositeRoles
// But in addCompositeRoles, it first checks getRoleById which may throw NotFoundException
// Actually, looking at the code, if client is not found, it throws IllegalArgumentException
// But getRoleById might throw NotFoundException first
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.addCompositeRoles(ROLE_ID, List.of("child-1"), REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME));
}
// ==================== Tests removeCompositeRoles - Cas limites ====================
@Test
void testRemoveCompositeRoles_RealmRole_ChildNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
RoleRepresentation parentRole = new RoleRepresentation();
parentRole.setId(ROLE_ID);
parentRole.setName("parent");
when(rolesResource.list()).thenReturn(List.of(parentRole));
// Child role not found - getRealmRoleById returns empty, so childRoleNames will be empty
// Should not throw, just log warning and skip
roleService.removeCompositeRoles(ROLE_ID, List.of("child-id"), REALM, TypeRole.REALM_ROLE, null);
// Verify that list was called
verify(rolesResource, atLeastOnce()).list();
}
@Test
void testRemoveCompositeRoles_ClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.clients()).thenReturn(clientsResource);
// Mock getRoleById to return a role
RoleRepresentation parentRole = new RoleRepresentation();
parentRole.setId(ROLE_ID);
parentRole.setName("parent");
when(rolesResource.list()).thenReturn(List.of(parentRole));
when(rolesResource.get("parent")).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(parentRole);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
// When client not found, it throws IllegalArgumentException
// But getRoleById might throw NotFoundException first
assertThrows(jakarta.ws.rs.NotFoundException.class, () ->
roleService.removeCompositeRoles(ROLE_ID, List.of("child-1"), REALM, TypeRole.CLIENT_ROLE, CLIENT_NAME));
}
// ==================== Tests getAllRealmRoles - Cas limites ====================
@Test
void testGetAllRealmRoles_RealmNotFound() {
// realmExists returns false, so it throws IllegalArgumentException
when(keycloakAdminClient.realmExists(REALM)).thenReturn(false);
// But if realmExists throws an exception, it might be wrapped
// Let's test both cases
try {
roleService.getAllRealmRoles(REALM);
fail("Should have thrown an exception");
} catch (IllegalArgumentException e) {
// Expected when realmExists returns false
assertTrue(e.getMessage().contains("n'existe pas"));
} catch (RuntimeException e) {
// Also possible if realmExists throws
assertTrue(e.getMessage().contains("n'existe pas") ||
e.getMessage().contains("récupération des rôles realm"));
}
}
@Test
void testGetAllRealmRoles_NotFoundException() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new jakarta.ws.rs.NotFoundException());
assertThrows(IllegalArgumentException.class, () ->
roleService.getAllRealmRoles(REALM));
}
@Test
void testGetAllRealmRoles_ExceptionWith404() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Server response is: 404"));
assertThrows(IllegalArgumentException.class, () ->
roleService.getAllRealmRoles(REALM));
}
@Test
void testGetAllRealmRoles_ExceptionWithNotFound() {
when(keycloakAdminClient.realmExists(REALM)).thenReturn(true);
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Not Found"));
assertThrows(IllegalArgumentException.class, () ->
roleService.getAllRealmRoles(REALM));
}
// ==================== Tests getAllClientRoles - Cas limites ====================
@Test
void testGetAllClientRoles_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
List<RoleDTO> result = roleService.getAllClientRoles(REALM, CLIENT_NAME);
assertNotNull(result);
assertTrue(result.isEmpty());
}
// ==================== Tests createClientRole - Cas limites ====================
@Test
void testCreateClientRole_ClientNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(Collections.emptyList());
RoleDTO roleDTO = RoleDTO.builder()
.name(ROLE_NAME)
.build();
assertThrows(IllegalArgumentException.class, () ->
roleService.createClientRole(roleDTO, REALM, CLIENT_NAME));
}
@Test
void testCreateClientRole_RoleAlreadyExists() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.clients()).thenReturn(clientsResource);
ClientRepresentation client = new ClientRepresentation();
client.setId("client-123");
when(clientsResource.findByClientId(CLIENT_NAME)).thenReturn(List.of(client));
when(clientsResource.get("client-123")).thenReturn(clientResource);
when(clientResource.roles()).thenReturn(rolesResource);
when(rolesResource.get(ROLE_NAME)).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(new RoleRepresentation());
RoleDTO roleDTO = RoleDTO.builder()
.name(ROLE_NAME)
.build();
assertThrows(IllegalArgumentException.class, () ->
roleService.createClientRole(roleDTO, REALM, CLIENT_NAME));
}
// ==================== Tests countUsersWithRole - Cas limites ====================
@Test
void testCountUsersWithRole_RoleNotFound() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
long count = roleService.countUsersWithRole(ROLE_ID, REALM, TypeRole.REALM_ROLE, null);
assertEquals(0, count);
}
@Test
void testCountUsersWithRole_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.users()).thenReturn(usersResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setId(ROLE_ID);
roleRep.setName(ROLE_NAME);
when(rolesResource.list()).thenReturn(List.of(roleRep));
when(usersResource.list()).thenThrow(new RuntimeException("Error"));
long count = roleService.countUsersWithRole(ROLE_ID, REALM, TypeRole.REALM_ROLE, null);
assertEquals(0, count); // Should return 0 on exception
}
}

View File

@@ -0,0 +1,128 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.role.RoleAssignmentDTO;
import dev.lions.user.manager.dto.role.RoleDTO;
import dev.lions.user.manager.enums.role.TypeRole;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.*;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class RoleServiceImplTest {
@Mock
KeycloakAdminClient keycloakAdminClient;
@Mock
Keycloak keycloakInstance;
@Mock
RealmResource realmResource;
@Mock
RolesResource rolesResource;
@Mock
RoleResource roleResource;
@Mock
UsersResource usersResource;
@Mock
UserResource userResource;
@Mock
RoleMappingResource roleMappingResource;
@Mock
RoleScopeResource roleScopeResource;
@InjectMocks
RoleServiceImpl roleService;
private static final String REALM = "test-realm";
@Test
void testCreateRealmRole() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
// Check not found initially, then return created role
RoleRepresentation createdRep = new RoleRepresentation();
createdRep.setName("role");
createdRep.setId("1");
when(rolesResource.get("role")).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenThrow(new jakarta.ws.rs.NotFoundException())
.thenReturn(createdRep);
// Mock create
doNothing().when(rolesResource).create(any(RoleRepresentation.class));
RoleDTO input = RoleDTO.builder().name("role").description("desc").build();
RoleDTO result = roleService.createRealmRole(input, REALM);
assertNotNull(result);
assertEquals("role", result.getName());
}
@Test
void testDeleteRole() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
// find by id logic uses list()
RoleRepresentation rep = new RoleRepresentation();
rep.setId("1");
rep.setName("role");
when(rolesResource.list()).thenReturn(Collections.singletonList(rep));
roleService.deleteRole("1", REALM, TypeRole.REALM_ROLE, null);
verify(rolesResource).deleteRole("role");
}
@Test
void testAssignRolesToUser() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm(REALM)).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.get("u1")).thenReturn(userResource);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(roleScopeResource);
RoleRepresentation roleRep = new RoleRepresentation();
roleRep.setName("role1");
when(rolesResource.get("role1")).thenReturn(roleResource);
when(roleResource.toRepresentation()).thenReturn(roleRep);
RoleAssignmentDTO assignment = RoleAssignmentDTO.builder()
.userId("u1")
.realmName(REALM)
.typeRole(TypeRole.REALM_ROLE)
.roleNames(Collections.singletonList("role1"))
.build();
roleService.assignRolesToUser(assignment);
verify(roleScopeResource).add(anyList());
}
}

View File

@@ -0,0 +1,249 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.resource.*;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.representations.info.ServerInfoRepresentation;
import org.keycloak.representations.info.SystemInfoRepresentation; // Correct import
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class SyncServiceImplTest {
@Mock
KeycloakAdminClient keycloakAdminClient;
@Mock
Keycloak keycloakInstance;
@Mock
RealmsResource realmsResource;
@Mock
RealmResource realmResource;
@Mock
UsersResource usersResource;
@Mock
RolesResource rolesResource;
@Mock
ServerInfoResource serverInfoResource;
@InjectMocks
SyncServiceImpl syncService;
// Correcting inner class usage if needed, but assuming standard Keycloak
// representations
// ServerInfoRepresentation contains SystemInfoRepresentation
@Test
void testSyncUsersFromRealm() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm("realm")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.list()).thenReturn(Collections.singletonList(new UserRepresentation()));
int count = syncService.syncUsersFromRealm("realm");
assertEquals(1, count);
}
@Test
void testSyncRolesFromRealm() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm("realm")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.singletonList(new RoleRepresentation()));
int count = syncService.syncRolesFromRealm("realm");
assertEquals(1, count);
}
@Test
void testSyncAllRealms() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realms()).thenReturn(realmsResource);
RealmRepresentation realmRep = new RealmRepresentation();
realmRep.setRealm("realm1");
when(realmsResource.findAll()).thenReturn(Collections.singletonList(realmRep));
// Sync logic calls realm() again
when(keycloakInstance.realm("realm1")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.list()).thenReturn(Collections.emptyList());
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenReturn(Collections.emptyList());
Map<String, Integer> result = syncService.syncAllRealms();
assertTrue(result.containsKey("realm1"));
assertEquals(0, result.get("realm1"));
}
@Test
void testIsKeycloakAvailable() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.serverInfo()).thenReturn(serverInfoResource);
when(serverInfoResource.getInfo()).thenReturn(new ServerInfoRepresentation());
assertTrue(syncService.isKeycloakAvailable());
}
@Test
void testGetKeycloakHealthInfo() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.serverInfo()).thenReturn(serverInfoResource);
ServerInfoRepresentation info = new ServerInfoRepresentation();
SystemInfoRepresentation systemInfo = new SystemInfoRepresentation();
systemInfo.setVersion("1.0");
info.setSystemInfo(systemInfo);
when(serverInfoResource.getInfo()).thenReturn(info);
when(keycloakInstance.realms()).thenReturn(realmsResource);
when(realmsResource.findAll()).thenReturn(Collections.emptyList());
Map<String, Object> health = syncService.getKeycloakHealthInfo();
assertTrue((Boolean) health.get("overallHealthy"));
assertEquals("1.0", health.get("keycloakVersion"));
}
@Test
void testSyncUsersFromRealm_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm("realm")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.list()).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () -> syncService.syncUsersFromRealm("realm"));
}
@Test
void testSyncRolesFromRealm_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm("realm")).thenReturn(realmResource);
when(realmResource.roles()).thenReturn(rolesResource);
when(rolesResource.list()).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () -> syncService.syncRolesFromRealm("realm"));
}
@Test
void testSyncAllRealms_WithException() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realms()).thenReturn(realmsResource);
RealmRepresentation realmRep = new RealmRepresentation();
realmRep.setRealm("realm1");
when(realmsResource.findAll()).thenReturn(Collections.singletonList(realmRep));
// Mock exception during sync
when(keycloakInstance.realm("realm1")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.list()).thenThrow(new RuntimeException("Sync error"));
Map<String, Integer> result = syncService.syncAllRealms();
assertTrue(result.containsKey("realm1"));
assertEquals(0, result.get("realm1")); // Should be 0 on error
}
@Test
void testSyncAllRealms_ExceptionInFindAll() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realms()).thenReturn(realmsResource);
when(realmsResource.findAll()).thenThrow(new RuntimeException("Connection error"));
Map<String, Integer> result = syncService.syncAllRealms();
assertTrue(result.isEmpty());
}
// Note: checkDataConsistency doesn't actually throw exceptions in the current implementation
// The try-catch block is there for future use, but currently always succeeds
// So we test the success path in testCheckDataConsistency_Success
@Test
void testForceSyncRealm_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.realm("realm")).thenReturn(realmResource);
when(realmResource.users()).thenReturn(usersResource);
when(usersResource.list()).thenThrow(new RuntimeException("Sync error"));
Map<String, Object> stats = syncService.forceSyncRealm("realm");
assertFalse((Boolean) stats.get("success"));
assertNotNull(stats.get("error"));
assertNotNull(stats.get("durationMs"));
}
@Test
void testIsKeycloakAvailable_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.serverInfo()).thenReturn(serverInfoResource);
when(serverInfoResource.getInfo()).thenThrow(new RuntimeException("Connection refused"));
assertFalse(syncService.isKeycloakAvailable());
}
@Test
void testGetKeycloakHealthInfo_Exception() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.serverInfo()).thenReturn(serverInfoResource);
when(serverInfoResource.getInfo()).thenThrow(new RuntimeException("Connection error"));
Map<String, Object> health = syncService.getKeycloakHealthInfo();
assertFalse((Boolean) health.get("overallHealthy"));
assertFalse((Boolean) health.get("keycloakAccessible"));
assertNotNull(health.get("errorMessage"));
}
@Test
void testGetKeycloakHealthInfo_RealmsException() {
when(keycloakAdminClient.getInstance()).thenReturn(keycloakInstance);
when(keycloakInstance.serverInfo()).thenReturn(serverInfoResource);
ServerInfoRepresentation info = new ServerInfoRepresentation();
SystemInfoRepresentation systemInfo = new SystemInfoRepresentation();
systemInfo.setVersion("1.0");
info.setSystemInfo(systemInfo);
when(serverInfoResource.getInfo()).thenReturn(info);
when(keycloakInstance.realms()).thenReturn(realmsResource);
when(realmsResource.findAll()).thenThrow(new RuntimeException("Realms error"));
Map<String, Object> health = syncService.getKeycloakHealthInfo();
assertTrue((Boolean) health.get("overallHealthy")); // Still healthy if server is accessible
assertFalse((Boolean) health.get("realmsAccessible"));
}
@Test
void testCheckDataConsistency_Success() {
Map<String, Object> report = syncService.checkDataConsistency("realm");
assertEquals("realm", report.get("realmName"));
assertEquals("ok", report.get("status"));
assertEquals("Cohérence vérifiée", report.get("message"));
}
@Test
void testGetLastSyncStatus() {
Map<String, Object> status = syncService.getLastSyncStatus("realm");
assertEquals("realm", status.get("realmName"));
assertEquals("completed", status.get("status"));
assertNotNull(status.get("lastSyncTime"));
}
}

View File

@@ -0,0 +1,318 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests complets pour UserServiceImpl pour atteindre 100% de couverture
* Couvre les branches manquantes : filterUsers, searchUsers avec différents critères, etc.
*/
@ExtendWith(MockitoExtension.class)
class UserServiceImplCompleteTest {
private static final String REALM = "test-realm";
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private UsersResource usersResource;
@InjectMocks
private UserServiceImpl userService;
@BeforeEach
void setUp() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
}
@Test
void testSearchUsers_WithSearchTerm() {
UserRepresentation user = new UserRepresentation();
user.setUsername("testuser");
user.setEnabled(true);
when(usersResource.search("test", 0, 10)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.searchTerm("test")
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
verify(usersResource).search("test", 0, 10);
}
@Test
void testSearchUsers_WithUsername() {
UserRepresentation user = new UserRepresentation();
user.setUsername("testuser");
user.setEnabled(true);
when(usersResource.search("testuser", 0, 10, true)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.username("testuser")
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
verify(usersResource).search("testuser", 0, 10, true);
}
@Test
void testSearchUsers_WithEmail() {
UserRepresentation user = new UserRepresentation();
user.setUsername("testuser");
user.setEmail("test@example.com");
user.setEnabled(true);
when(usersResource.searchByEmail("test@example.com", true)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.email("test@example.com")
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
verify(usersResource).searchByEmail("test@example.com", true);
}
@Test
void testSearchUsers_ListAll() {
UserRepresentation user = new UserRepresentation();
user.setUsername("testuser");
user.setEnabled(true);
when(usersResource.list(0, 10)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
verify(usersResource).list(0, 10);
}
@Test
void testSearchUsers_WithEnabledFilter() {
UserRepresentation enabledUser = new UserRepresentation();
enabledUser.setUsername("enabled");
enabledUser.setEnabled(true);
UserRepresentation disabledUser = new UserRepresentation();
disabledUser.setUsername("disabled");
disabledUser.setEnabled(false);
when(usersResource.list(0, 10)).thenReturn(List.of(enabledUser, disabledUser));
when(usersResource.count()).thenReturn(2);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.enabled(true)
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
// Seul l'utilisateur activé devrait être retourné
assertEquals(1, result.getUsers().size());
assertTrue(result.getUsers().get(0).getEnabled());
}
@Test
void testSearchUsers_WithEmailVerifiedFilter() {
UserRepresentation verifiedUser = new UserRepresentation();
verifiedUser.setUsername("verified");
verifiedUser.setEmailVerified(true);
verifiedUser.setEnabled(true);
UserRepresentation unverifiedUser = new UserRepresentation();
unverifiedUser.setUsername("unverified");
unverifiedUser.setEmailVerified(false);
unverifiedUser.setEnabled(true);
when(usersResource.list(0, 10)).thenReturn(List.of(verifiedUser, unverifiedUser));
when(usersResource.count()).thenReturn(2);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.emailVerified(true)
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
// Seul l'utilisateur avec email vérifié devrait être retourné
assertEquals(1, result.getUsers().size());
assertTrue(result.getUsers().get(0).getEmailVerified());
}
@Test
void testSearchUsers_WithBlankSearchTerm() {
UserRepresentation user = new UserRepresentation();
user.setUsername("testuser");
user.setEnabled(true);
when(usersResource.list(0, 10)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.searchTerm(" ") // Blank search term
.page(0)
.pageSize(10)
.build();
var result = userService.searchUsers(criteria);
assertNotNull(result);
// Devrait utiliser list() au lieu de search() pour un terme vide
verify(usersResource).list(0, 10);
}
@Test
void testUpdateUser_WithAllFields() {
UserResource userResource = mock(UserResource.class);
when(usersResource.get("user-id")).thenReturn(userResource);
UserRepresentation existingUser = new UserRepresentation();
existingUser.setId("user-id");
existingUser.setUsername("olduser");
existingUser.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(existingUser);
UserDTO userDTO = UserDTO.builder()
.email("new@example.com")
.prenom("John")
.nom("Doe")
.enabled(false)
.emailVerified(true)
.attributes(java.util.Map.of("key", java.util.List.of("value")))
.build();
UserRepresentation updatedUser = new UserRepresentation();
updatedUser.setId("user-id");
updatedUser.setUsername("olduser");
updatedUser.setEmail("new@example.com");
updatedUser.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(existingUser, updatedUser);
UserDTO result = userService.updateUser("user-id", userDTO, REALM);
assertNotNull(result);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testUpdateUser_WithNullFields() {
UserResource userResource = mock(UserResource.class);
when(usersResource.get("user-id")).thenReturn(userResource);
UserRepresentation existingUser = new UserRepresentation();
existingUser.setId("user-id");
existingUser.setUsername("olduser");
existingUser.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(existingUser);
UserDTO userDTO = UserDTO.builder()
.email(null)
.prenom(null)
.nom(null)
.enabled(null)
.emailVerified(null)
.attributes(null)
.build();
UserRepresentation updatedUser = new UserRepresentation();
updatedUser.setId("user-id");
updatedUser.setUsername("olduser");
updatedUser.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(existingUser, updatedUser);
UserDTO result = userService.updateUser("user-id", userDTO, REALM);
assertNotNull(result);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testDeleteUser_HardDelete() {
UserResource userResource = mock(UserResource.class);
when(usersResource.get("user-id")).thenReturn(userResource);
userService.deleteUser("user-id", REALM, true);
verify(userResource).remove();
verify(userResource, never()).update(any());
}
@Test
void testDeleteUser_SoftDelete() {
UserResource userResource = mock(UserResource.class);
when(usersResource.get("user-id")).thenReturn(userResource);
UserRepresentation user = new UserRepresentation();
user.setId("user-id");
user.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(user);
userService.deleteUser("user-id", REALM, false);
verify(userResource, never()).remove();
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testSearchUsers_Exception() {
when(usersResource.list(0, 10)).thenThrow(new RuntimeException("Connection error"));
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.page(0)
.pageSize(10)
.build();
assertThrows(RuntimeException.class, () ->
userService.searchUsers(criteria));
}
}

View File

@@ -0,0 +1,535 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.user.UserDTO;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.resource.RoleMappingResource;
import org.keycloak.admin.client.resource.RoleScopeResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests supplémentaires pour UserServiceImpl pour améliorer la couverture
*/
@ExtendWith(MockitoExtension.class)
class UserServiceImplExtendedTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private UsersResource usersResource;
@Mock
private UserResource userResource;
@Mock
private RoleMappingResource roleMappingResource;
@Mock
private RoleScopeResource roleScopeResource;
@InjectMocks
private UserServiceImpl userService;
private static final String REALM = "test-realm";
private static final String USER_ID = "user-123";
@Test
void testDeactivateUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(userRep);
userService.deactivateUser(USER_ID, REALM, "Test reason");
verify(userResource).update(argThat(rep -> !rep.isEnabled()));
}
@Test
void testResetPassword() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
userService.resetPassword(USER_ID, REALM, "newPassword123", true);
verify(userResource).resetPassword(any());
}
@Test
void testSendVerificationEmail() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
userService.sendVerificationEmail(USER_ID, REALM);
verify(userResource).sendVerifyEmail();
}
@Test
void testLogoutAllSessions() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.getUserSessions()).thenReturn(Collections.emptyList());
int count = userService.logoutAllSessions(USER_ID, REALM);
verify(userResource).logout();
assertEquals(0, count);
}
@Test
void testGetActiveSessions() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
// Mock UserSessionRepresentation
org.keycloak.representations.idm.UserSessionRepresentation session1 =
mock(org.keycloak.representations.idm.UserSessionRepresentation.class);
when(session1.getId()).thenReturn("session-1");
org.keycloak.representations.idm.UserSessionRepresentation session2 =
mock(org.keycloak.representations.idm.UserSessionRepresentation.class);
when(session2.getId()).thenReturn("session-2");
when(userResource.getUserSessions()).thenReturn(List.of(session1, session2));
List<String> sessions = userService.getActiveSessions(USER_ID, REALM);
assertNotNull(sessions);
assertEquals(2, sessions.size());
assertTrue(sessions.contains("session-1"));
assertTrue(sessions.contains("session-2"));
}
@Test
void testGetActiveSessions_Empty() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.getUserSessions()).thenReturn(Collections.emptyList());
List<String> sessions = userService.getActiveSessions(USER_ID, REALM);
assertNotNull(sessions);
assertTrue(sessions.isEmpty());
}
@Test
void testGetActiveSessions_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.getUserSessions()).thenThrow(new RuntimeException("Error"));
List<String> sessions = userService.getActiveSessions(USER_ID, REALM);
assertNotNull(sessions);
assertTrue(sessions.isEmpty());
}
@Test
void testGetAllUsers() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user1 = new UserRepresentation();
user1.setId("user-1");
user1.setUsername("user1");
user1.setEnabled(true); // Important: définir enabled pour éviter NullPointerException
UserRepresentation user2 = new UserRepresentation();
user2.setId("user-2");
user2.setUsername("user2");
user2.setEnabled(true); // Important: définir enabled pour éviter NullPointerException
when(usersResource.list(anyInt(), anyInt())).thenReturn(List.of(user1, user2));
when(usersResource.count()).thenReturn(2);
var result = userService.getAllUsers(REALM, 0, 20);
assertNotNull(result);
assertEquals(2, result.getUsers().size());
assertEquals(2L, result.getTotalCount());
}
@Test
void testGetUserById_NotFound() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.toRepresentation()).thenThrow(new jakarta.ws.rs.NotFoundException());
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertFalse(result.isPresent());
}
@Test
void testGetUserById_ExceptionWith404() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
RuntimeException exception = new RuntimeException("Server response is: 404");
when(userResource.toRepresentation()).thenThrow(exception);
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertFalse(result.isPresent());
}
@Test
void testGetUserByUsername_Success() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setUsername("testuser");
userRep.setEnabled(true);
when(usersResource.search("testuser", 0, 1, true)).thenReturn(List.of(userRep));
Optional<UserDTO> result = userService.getUserByUsername("testuser", REALM);
assertTrue(result.isPresent());
assertEquals("testuser", result.get().getUsername());
}
@Test
void testGetUserByUsername_NotFound() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("nonexistent", 0, 1, true)).thenReturn(Collections.emptyList());
Optional<UserDTO> result = userService.getUserByUsername("nonexistent", REALM);
assertFalse(result.isPresent());
}
@Test
void testGetUserByUsername_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("testuser", 0, 1, true)).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () ->
userService.getUserByUsername("testuser", REALM));
}
@Test
void testGetUserByEmail_Success() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setEmail("test@example.com");
userRep.setEnabled(true);
when(usersResource.searchByEmail("test@example.com", true)).thenReturn(List.of(userRep));
Optional<UserDTO> result = userService.getUserByEmail("test@example.com", REALM);
assertTrue(result.isPresent());
assertEquals("test@example.com", result.get().getEmail());
}
@Test
void testGetUserByEmail_NotFound() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.searchByEmail("nonexistent@example.com", true)).thenReturn(Collections.emptyList());
Optional<UserDTO> result = userService.getUserByEmail("nonexistent@example.com", REALM);
assertFalse(result.isPresent());
}
@Test
void testGetUserByEmail_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.searchByEmail("test@example.com", true)).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () ->
userService.getUserByEmail("test@example.com", REALM));
}
@Test
void testCreateUser_UsernameExists() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
// usernameExists calls search which should return a non-empty list
UserRepresentation existingUser = new UserRepresentation();
existingUser.setUsername("existinguser");
existingUser.setEnabled(true);
when(usersResource.search("existinguser", 0, 1, true)).thenReturn(List.of(existingUser));
UserDTO userDTO = UserDTO.builder()
.username("existinguser")
.email("test@example.com")
.build();
// createUser catches all exceptions and rethrows as RuntimeException
RuntimeException exception = assertThrows(RuntimeException.class, () ->
userService.createUser(userDTO, REALM));
assertTrue(exception.getCause() instanceof IllegalArgumentException);
assertTrue(exception.getCause().getMessage().contains("existe déjà"));
}
@Test
void testCreateUser_EmailExists() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("newuser", 0, 1, true)).thenReturn(Collections.emptyList());
// emailExists calls searchByEmail which should return a non-empty list
UserRepresentation existingUser = new UserRepresentation();
existingUser.setEmail("existing@example.com");
existingUser.setEnabled(true);
when(usersResource.searchByEmail("existing@example.com", true)).thenReturn(List.of(existingUser));
UserDTO userDTO = UserDTO.builder()
.username("newuser")
.email("existing@example.com")
.build();
// createUser catches all exceptions and rethrows as RuntimeException
RuntimeException exception = assertThrows(RuntimeException.class, () ->
userService.createUser(userDTO, REALM));
assertTrue(exception.getCause() instanceof IllegalArgumentException);
assertTrue(exception.getCause().getMessage().contains("existe déjà"));
}
@Test
void testCreateUser_StatusNot201() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("newuser", 0, 1, true)).thenReturn(Collections.emptyList());
UserDTO userDTO = UserDTO.builder()
.username("newuser")
.email("test@example.com")
.build();
jakarta.ws.rs.core.Response response = mock(jakarta.ws.rs.core.Response.class);
when(response.getStatus()).thenReturn(400);
when(response.getStatusInfo()).thenReturn(jakarta.ws.rs.core.Response.Status.BAD_REQUEST);
when(usersResource.create(any())).thenReturn(response);
assertThrows(RuntimeException.class, () ->
userService.createUser(userDTO, REALM));
}
@Test
void testCreateUser_WithTemporaryPassword() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("newuser", 0, 1, true)).thenReturn(Collections.emptyList());
UserDTO userDTO = UserDTO.builder()
.username("newuser")
.email("test@example.com")
.temporaryPassword("temp123")
.temporaryPasswordFlag(true)
.build();
jakarta.ws.rs.core.Response response = mock(jakarta.ws.rs.core.Response.class);
when(response.getStatus()).thenReturn(201);
java.net.URI location = java.net.URI.create("http://localhost/users/" + USER_ID);
when(response.getLocation()).thenReturn(location);
when(usersResource.create(any())).thenReturn(response);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation createdUser = new UserRepresentation();
createdUser.setId(USER_ID);
createdUser.setUsername("newuser");
createdUser.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(createdUser);
UserDTO result = userService.createUser(userDTO, REALM);
assertNotNull(result);
verify(userResource).resetPassword(any());
}
@Test
void testCreateUser_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("newuser", 0, 1, true)).thenThrow(new RuntimeException("Connection error"));
UserDTO userDTO = UserDTO.builder()
.username("newuser")
.email("test@example.com")
.build();
assertThrows(RuntimeException.class, () ->
userService.createUser(userDTO, REALM));
}
@Test
void testUpdateUser_WithEmailAndPrenom() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation existingUser = new UserRepresentation();
existingUser.setId(USER_ID);
existingUser.setUsername("testuser");
existingUser.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(existingUser);
UserDTO userDTO = UserDTO.builder()
.id(USER_ID)
.email("newemail@example.com")
.prenom("John")
.build();
UserDTO result = userService.updateUser(USER_ID, userDTO, REALM);
assertNotNull(result);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testActivateUser_Success() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation user = new UserRepresentation();
user.setId(USER_ID);
user.setEnabled(false);
when(userResource.toRepresentation()).thenReturn(user);
userService.activateUser(USER_ID, REALM);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testActivateUser_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.toRepresentation()).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () ->
userService.activateUser(USER_ID, REALM));
}
@Test
void testDeactivateUser_Success() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation user = new UserRepresentation();
user.setId(USER_ID);
user.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(user);
userService.deactivateUser(USER_ID, REALM, "Test reason");
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testDeactivateUser_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.toRepresentation()).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () ->
userService.deactivateUser(USER_ID, REALM, "Test reason"));
}
@Test
void testSuspendUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation user = new UserRepresentation();
user.setId(USER_ID);
user.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(user);
userService.suspendUser(USER_ID, REALM, "Suspension reason", 30);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testUnlockUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation user = new UserRepresentation();
user.setId(USER_ID);
user.setEnabled(false);
when(userResource.toRepresentation()).thenReturn(user);
userService.unlockUser(USER_ID, REALM);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testLogoutAllSessions_WithSessions() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
org.keycloak.representations.idm.UserSessionRepresentation session1 =
mock(org.keycloak.representations.idm.UserSessionRepresentation.class);
org.keycloak.representations.idm.UserSessionRepresentation session2 =
mock(org.keycloak.representations.idm.UserSessionRepresentation.class);
when(userResource.getUserSessions()).thenReturn(List.of(session1, session2));
doNothing().when(userResource).logout();
int count = userService.logoutAllSessions(USER_ID, REALM);
assertEquals(2, count);
verify(userResource).logout();
}
@Test
void testLogoutAllSessions_NoSessions() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.getUserSessions()).thenReturn(Collections.emptyList());
doNothing().when(userResource).logout();
int count = userService.logoutAllSessions(USER_ID, REALM);
assertEquals(0, count);
verify(userResource).logout();
}
@Test
void testLogoutAllSessions_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.getUserSessions()).thenThrow(new RuntimeException("Connection error"));
assertThrows(RuntimeException.class, () ->
userService.logoutAllSessions(USER_ID, REALM));
}
@Test
void testGetActiveSessions_Success() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
org.keycloak.representations.idm.UserSessionRepresentation session1 =
mock(org.keycloak.representations.idm.UserSessionRepresentation.class);
org.keycloak.representations.idm.UserSessionRepresentation session2 =
mock(org.keycloak.representations.idm.UserSessionRepresentation.class);
when(session1.getId()).thenReturn("session-1");
when(session2.getId()).thenReturn("session-2");
when(userResource.getUserSessions()).thenReturn(List.of(session1, session2));
List<String> sessions = userService.getActiveSessions(USER_ID, REALM);
assertNotNull(sessions);
assertEquals(2, sessions.size());
assertTrue(sessions.contains("session-1"));
assertTrue(sessions.contains("session-2"));
}
}

View File

@@ -0,0 +1,569 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* Tests d'intégration pour UserServiceImpl - Cas limites et branches conditionnelles complexes
*/
@ExtendWith(MockitoExtension.class)
class UserServiceImplIntegrationTest {
@Mock
private KeycloakAdminClient keycloakAdminClient;
@Mock
private UsersResource usersResource;
@Mock
private UserResource userResource;
@InjectMocks
private UserServiceImpl userService;
private static final String REALM = "test-realm";
private static final String USER_ID = "user-123";
// ==================== Tests de recherche - Cas limites ====================
@Test
void testSearchUsers_WithSearchTerm() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setId("1");
user.setUsername("testuser");
user.setEnabled(true);
user.setEmailVerified(true);
when(usersResource.search("test", 0, 20)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.searchTerm("test")
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
verify(usersResource).search("test", 0, 20);
}
@Test
void testSearchUsers_WithSearchTerm_Blank() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setId("1");
user.setUsername("user1");
user.setEnabled(true);
when(usersResource.list(0, 20)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.searchTerm(" ") // Blank string
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
verify(usersResource).list(0, 20); // Should use list() when searchTerm is blank
}
@Test
void testSearchUsers_WithUsername() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setId("1");
user.setUsername("exactuser");
user.setEnabled(true);
when(usersResource.search("exactuser", 0, 20, true)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.username("exactuser")
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
verify(usersResource).search("exactuser", 0, 20, true);
}
@Test
void testSearchUsers_WithEmail() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setId("1");
user.setEmail("test@example.com");
user.setEnabled(true);
when(usersResource.searchByEmail("test@example.com", true)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.email("test@example.com")
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
verify(usersResource).searchByEmail("test@example.com", true);
}
@Test
void testSearchUsers_NoCriteria() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setId("1");
user.setUsername("user1");
user.setEnabled(true);
when(usersResource.list(0, 20)).thenReturn(List.of(user));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
verify(usersResource).list(0, 20);
}
// ==================== Tests de filtrage - Cas limites ====================
@Test
void testSearchUsers_FilterByEnabled_True() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation enabledUser = new UserRepresentation();
enabledUser.setId("1");
enabledUser.setUsername("enabled");
enabledUser.setEnabled(true);
UserRepresentation disabledUser = new UserRepresentation();
disabledUser.setId("2");
disabledUser.setUsername("disabled");
disabledUser.setEnabled(false);
when(usersResource.list(0, 20)).thenReturn(List.of(enabledUser, disabledUser));
when(usersResource.count()).thenReturn(2);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.enabled(true)
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
assertTrue(result.getUsers().get(0).getEnabled());
}
@Test
void testSearchUsers_FilterByEnabled_False() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation enabledUser = new UserRepresentation();
enabledUser.setId("1");
enabledUser.setUsername("enabled");
enabledUser.setEnabled(true);
UserRepresentation disabledUser = new UserRepresentation();
disabledUser.setId("2");
disabledUser.setUsername("disabled");
disabledUser.setEnabled(false);
when(usersResource.list(0, 20)).thenReturn(List.of(enabledUser, disabledUser));
when(usersResource.count()).thenReturn(2);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.enabled(false)
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
assertFalse(result.getUsers().get(0).getEnabled());
}
@Test
void testSearchUsers_FilterByEmailVerified_True() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation verifiedUser = new UserRepresentation();
verifiedUser.setId("1");
verifiedUser.setUsername("verified");
verifiedUser.setEmail("test@example.com");
verifiedUser.setEmailVerified(true);
verifiedUser.setEnabled(true);
UserRepresentation unverifiedUser = new UserRepresentation();
unverifiedUser.setId("2");
unverifiedUser.setUsername("unverified");
unverifiedUser.setEmail("test2@example.com");
unverifiedUser.setEmailVerified(false);
unverifiedUser.setEnabled(true);
when(usersResource.list(0, 20)).thenReturn(List.of(verifiedUser, unverifiedUser));
when(usersResource.count()).thenReturn(2);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.emailVerified(true)
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
assertTrue(result.getUsers().get(0).getEmailVerified());
}
@Test
void testSearchUsers_FilterByEnabledAndEmailVerified() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user1 = new UserRepresentation();
user1.setId("1");
user1.setUsername("user1");
user1.setEnabled(true);
user1.setEmailVerified(true);
UserRepresentation user2 = new UserRepresentation();
user2.setId("2");
user2.setUsername("user2");
user2.setEnabled(true);
user2.setEmailVerified(false);
UserRepresentation user3 = new UserRepresentation();
user3.setId("3");
user3.setUsername("user3");
user3.setEnabled(false);
user3.setEmailVerified(true);
when(usersResource.list(0, 20)).thenReturn(List.of(user1, user2, user3));
when(usersResource.count()).thenReturn(3);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.enabled(true)
.emailVerified(true)
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
assertEquals("user1", result.getUsers().get(0).getUsername());
}
@Test
void testSearchUsers_FilterByEnabled_Null() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user1 = new UserRepresentation();
user1.setId("1");
user1.setUsername("user1");
user1.setEnabled(true);
UserRepresentation user2 = new UserRepresentation();
user2.setId("2");
user2.setUsername("user2");
user2.setEnabled(false);
when(usersResource.list(0, 20)).thenReturn(List.of(user1, user2));
when(usersResource.count()).thenReturn(2);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.enabled(null) // Null should not filter
.page(0)
.pageSize(20)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(2, result.getUsers().size()); // Both users should be returned
}
// ==================== Tests getUserById - Cas limites ====================
@Test
void testGetUserById_WithRealmRoles() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setUsername("testuser");
userRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(userRep);
RoleRepresentation role1 = new RoleRepresentation();
role1.setName("role1");
RoleRepresentation role2 = new RoleRepresentation();
role2.setName("role2");
when(userResource.roles()).thenReturn(mock(org.keycloak.admin.client.resource.RoleMappingResource.class));
when(userResource.roles().realmLevel()).thenReturn(mock(org.keycloak.admin.client.resource.RoleScopeResource.class));
when(userResource.roles().realmLevel().listAll()).thenReturn(List.of(role1, role2));
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertTrue(result.isPresent());
assertEquals(USER_ID, result.get().getId());
}
@Test
void testGetUserById_WithEmptyRealmRoles() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setUsername("testuser");
userRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(userRep);
when(userResource.roles()).thenReturn(mock(org.keycloak.admin.client.resource.RoleMappingResource.class));
when(userResource.roles().realmLevel()).thenReturn(mock(org.keycloak.admin.client.resource.RoleScopeResource.class));
when(userResource.roles().realmLevel().listAll()).thenReturn(Collections.emptyList());
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertTrue(result.isPresent());
assertTrue(result.get().getRealmRoles() == null || result.get().getRealmRoles().isEmpty());
}
@Test
void testGetUserById_WithNullRealmRoles() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setUsername("testuser");
userRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(userRep);
when(userResource.roles()).thenReturn(mock(org.keycloak.admin.client.resource.RoleMappingResource.class));
when(userResource.roles().realmLevel()).thenReturn(mock(org.keycloak.admin.client.resource.RoleScopeResource.class));
when(userResource.roles().realmLevel().listAll()).thenReturn(null);
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertTrue(result.isPresent());
}
@Test
void testGetUserById_WithExceptionInRolesRetrieval() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId(USER_ID);
userRep.setUsername("testuser");
userRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(userRep);
when(userResource.roles()).thenReturn(mock(org.keycloak.admin.client.resource.RoleMappingResource.class));
when(userResource.roles().realmLevel()).thenReturn(mock(org.keycloak.admin.client.resource.RoleScopeResource.class));
when(userResource.roles().realmLevel().listAll()).thenThrow(new RuntimeException("Error getting roles"));
// Should not throw exception, just log warning
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertTrue(result.isPresent());
}
@Test
void testGetUserById_With404InExceptionMessage() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.toRepresentation()).thenThrow(new RuntimeException("Server response is: 404"));
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertFalse(result.isPresent());
}
@Test
void testGetUserById_With404InExceptionMessage_Variant() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get(USER_ID)).thenReturn(userResource);
when(userResource.toRepresentation()).thenThrow(new RuntimeException("Received: 'Server response is: 404'"));
Optional<UserDTO> result = userService.getUserById(USER_ID, REALM);
assertFalse(result.isPresent());
}
// ==================== Tests usernameExists et emailExists ====================
@Test
void testUsernameExists_True() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setUsername("existinguser");
when(usersResource.search("existinguser", 0, 1, true)).thenReturn(List.of(user));
boolean exists = userService.usernameExists("existinguser", REALM);
assertTrue(exists);
}
@Test
void testUsernameExists_False() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("nonexistent", 0, 1, true)).thenReturn(Collections.emptyList());
boolean exists = userService.usernameExists("nonexistent", REALM);
assertFalse(exists);
}
@Test
void testUsernameExists_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.search("erroruser", 0, 1, true)).thenThrow(new RuntimeException("Error"));
boolean exists = userService.usernameExists("erroruser", REALM);
assertFalse(exists); // Should return false on exception
}
@Test
void testEmailExists_True() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user = new UserRepresentation();
user.setEmail("existing@example.com");
when(usersResource.searchByEmail("existing@example.com", true)).thenReturn(List.of(user));
boolean exists = userService.emailExists("existing@example.com", REALM);
assertTrue(exists);
}
@Test
void testEmailExists_False() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.searchByEmail("nonexistent@example.com", true)).thenReturn(Collections.emptyList());
boolean exists = userService.emailExists("nonexistent@example.com", REALM);
assertFalse(exists);
}
@Test
void testEmailExists_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.searchByEmail("error@example.com", true)).thenThrow(new RuntimeException("Error"));
boolean exists = userService.emailExists("error@example.com", REALM);
assertFalse(exists); // Should return false on exception
}
// ==================== Tests countUsers ====================
@Test
void testCountUsers_Success() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.count()).thenReturn(42);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.build();
long count = userService.countUsers(criteria);
assertEquals(42L, count);
}
@Test
void testCountUsers_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.count()).thenThrow(new RuntimeException("Error"));
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.build();
long count = userService.countUsers(criteria);
assertEquals(0L, count); // Should return 0 on exception
}
// ==================== Tests searchUsers - Exception handling ====================
@Test
void testSearchUsers_Exception() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.list(0, 20)).thenThrow(new RuntimeException("Connection error"));
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.page(0)
.pageSize(20)
.build();
assertThrows(RuntimeException.class, () -> userService.searchUsers(criteria));
}
}

View File

@@ -0,0 +1,231 @@
package dev.lions.user.manager.service.impl;
import dev.lions.user.manager.client.KeycloakAdminClient;
import dev.lions.user.manager.dto.user.UserDTO;
import dev.lions.user.manager.dto.user.UserSearchCriteriaDTO;
import dev.lions.user.manager.dto.user.UserSearchResultDTO;
import jakarta.ws.rs.core.Response;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.keycloak.admin.client.resource.RoleMappingResource;
import org.keycloak.admin.client.resource.RoleScopeResource;
import org.keycloak.admin.client.resource.UserResource;
import org.keycloak.admin.client.resource.UsersResource;
import org.keycloak.representations.idm.RoleRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class UserServiceImplTest {
@Mock
KeycloakAdminClient keycloakAdminClient;
@Mock
UsersResource usersResource;
@Mock
UserResource userResource;
@Mock
RoleMappingResource roleMappingResource;
@Mock
RoleScopeResource roleScopeResource;
@InjectMocks
UserServiceImpl userService;
private static final String REALM = "test-realm";
@BeforeEach
void setUp() {
// lenient().when(keycloakAdminClient.getUsers(anyString())).thenReturn(usersResource);
}
@Test
void testSearchUsers() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId("1");
userRep.setUsername("user");
userRep.setEnabled(true);
when(usersResource.search(anyString(), anyInt(), anyInt())).thenReturn(Collections.singletonList(userRep));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.searchTerm("user")
.enabled(true)
.build();
UserSearchResultDTO result = userService.searchUsers(criteria);
assertNotNull(result);
assertEquals(1, result.getUsers().size());
assertEquals("user", result.getUsers().get(0).getUsername());
}
@Test
void testGetUserById() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get("1")).thenReturn(userResource);
UserRepresentation userRep = new UserRepresentation();
userRep.setId("1");
userRep.setUsername("user");
userRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(userRep);
when(userResource.roles()).thenReturn(roleMappingResource);
when(roleMappingResource.realmLevel()).thenReturn(roleScopeResource);
when(roleScopeResource.listAll()).thenReturn(Collections.emptyList());
Optional<UserDTO> result = userService.getUserById("1", REALM);
assertTrue(result.isPresent());
assertEquals("1", result.get().getId());
}
@Test
void testCreateUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserDTO newUser = UserDTO.builder().username("newuser").email("new@example.com").build();
// Check exists
when(usersResource.search("newuser", 0, 1, true)).thenReturn(Collections.emptyList());
when(usersResource.searchByEmail("new@example.com", true)).thenReturn(Collections.emptyList());
// Mock creation response
Response response = Response.status(201).location(URI.create("http://localhost/users/123")).build();
when(usersResource.create(any(UserRepresentation.class))).thenReturn(response);
// Mock get created user
when(usersResource.get("123")).thenReturn(userResource);
UserRepresentation createdRep = new UserRepresentation();
createdRep.setId("123");
createdRep.setUsername("newuser");
createdRep.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(createdRep);
UserDTO created = userService.createUser(newUser, REALM);
assertNotNull(created);
assertEquals("123", created.getId());
assertEquals("newuser", created.getUsername());
}
@Test
void testUpdateUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get("1")).thenReturn(userResource);
UserRepresentation existing = new UserRepresentation();
existing.setId("1");
existing.setEnabled(true);
when(userResource.toRepresentation()).thenReturn(existing);
UserDTO update = UserDTO.builder().username("updated").email("up@example.com").build();
UserDTO result = userService.updateUser("1", update, REALM);
verify(userResource).update(any(UserRepresentation.class));
assertNotNull(result);
}
@Test
void testDeleteUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get("1")).thenReturn(userResource);
userService.deleteUser("1", REALM, true);
verify(userResource).remove();
when(userResource.toRepresentation()).thenReturn(new UserRepresentation());
userService.deleteUser("1", REALM, false);
verify(userResource).update(any(UserRepresentation.class));
}
@Test
void testActivateUser() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
when(usersResource.get("1")).thenReturn(userResource);
when(userResource.toRepresentation()).thenReturn(new UserRepresentation());
userService.activateUser("1", REALM);
verify(userResource).update(argThat(rep -> rep.isEnabled()));
}
@Test
void testExportUsersToCSV() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
UserRepresentation user1 = new UserRepresentation();
user1.setId("1");
user1.setUsername("user1");
user1.setEmail("user1@example.com");
user1.setFirstName("First");
user1.setLastName("Last");
user1.setEnabled(true);
when(usersResource.list(any(), any())).thenReturn(Collections.singletonList(user1));
when(usersResource.count()).thenReturn(1);
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(REALM)
.build();
String csv = userService.exportUsersToCSV(criteria);
assertNotNull(csv);
assertTrue(csv.contains("username,email,firstName,lastName,enabled"));
assertTrue(csv.contains("user1,user1@example.com,First,Last,true"));
}
@Test
void testImportUsersFromCSV() {
when(keycloakAdminClient.getUsers(REALM)).thenReturn(usersResource);
// Mock checks for existing users
lenient().when(usersResource.search(anyString(), anyInt(), anyInt(), anyBoolean()))
.thenReturn(Collections.emptyList());
lenient().when(usersResource.searchByEmail(anyString(), anyBoolean())).thenReturn(Collections.emptyList());
// Mock creation response
Response response = Response.status(201).location(URI.create("http://localhost/users/123")).build();
lenient().when(usersResource.create(any(UserRepresentation.class))).thenReturn(response);
// Mock retrieving created user
lenient().when(usersResource.get(anyString())).thenReturn(userResource);
UserRepresentation createdRep = new UserRepresentation();
createdRep.setId("123");
createdRep.setUsername("imported");
createdRep.setEnabled(true);
lenient().when(userResource.toRepresentation()).thenReturn(createdRep);
// For password setting
lenient().doNothing().when(userResource)
.resetPassword(any(org.keycloak.representations.idm.CredentialRepresentation.class));
String csvContent = "username,email,firstName,lastName,enabled\n" +
"imported,imp@test.com,Imp,Orter,true";
int count = userService.importUsersFromCSV(csvContent, REALM);
assertEquals(1, count);
verify(usersResource, atLeastOnce()).create(argThat(u -> u.getUsername().equals("imported")));
}
}