package de.ozgcloud.admin.keycloak; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.keycloak.admin.client.resource.GroupsResource; import org.keycloak.representations.idm.GroupRepresentation; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import com.thedeanda.lorem.LoremIpsum; import jakarta.ws.rs.core.Response; class KeycloakApiServiceTest { @Spy @InjectMocks private KeycloakApiService service; @Mock private GroupsResource groupsResource; @Mock private Response response; @Nested class TestGetAllGroups { @Test void shouldCallGroupsResource() { service.getAllGroups(); verify(groupsResource).groups("", 0, Integer.MAX_VALUE, false); } @Test void shouldReturnGroupRepresentations() { var groupRepresentation = GroupRepresentationTestFactory.create(); when(groupsResource.groups("", 0, Integer.MAX_VALUE, false)).thenReturn(List.of(groupRepresentation)); var gotGroupRepresentations = service.getAllGroups(); assertThat(gotGroupRepresentations).containsExactly(groupRepresentation); } } @Nested class TestAddGroup { private final GroupRepresentation groupRepresentation = GroupRepresentationTestFactory.create(); private final String resourceId = GroupRepresentationTestFactory.create().getId(); @BeforeEach void init() { when(groupsResource.add(groupRepresentation)).thenReturn(response); doReturn(resourceId).when(service).getCreatedResourceIdFromResponse(response); } @Test void shouldCallGroupsResource() { callService(); verify(groupsResource).add(groupRepresentation); } @Test void shouldGetAddedResourceIdFromResponse() { callService(); verify(service).getCreatedResourceIdFromResponse(response); } @Test void shouldReturnAddedResourceId() { var id = callService(); assertThat(id).isEqualTo(resourceId); } private String callService() { return service.addGroup(groupRepresentation); } } @Nested class TestGetCreatedResourceIdFromResponse { private final String resourceId = GroupRepresentationTestFactory.create().getId(); private final String location = LoremIpsum.getInstance().getUrl(); @Test void shouldExtractResourceIdFromLocationHeader() { givenResponseCreated(); callService(); verify(service).extractResourceIdFromLocationHeader(location); } @Test void shouldReturnResourceId() { givenResponseCreated(); var id = callService(); assertThat(id).isEqualTo(resourceId); } @Test void shouldThrowExceptionIsStatusOtherThenCreated() { givenResponseUnauthorized(); assertThatExceptionOfType(ResourceCreationException.class).isThrownBy(this::callService) .withMessageStartingWith("Failed to add group - got response with status 403 (Unauthorized)"); } private void givenResponseCreated() { when(response.getStatus()).thenReturn(201); when(response.getHeaderString("Location")).thenReturn(location); doReturn(resourceId).when(service).extractResourceIdFromLocationHeader(location); } private void givenResponseUnauthorized() { when(response.getStatus()).thenReturn(403); when(response.getStatusInfo()).thenReturn(Response.Status.UNAUTHORIZED); } private String callService() { return service.getCreatedResourceIdFromResponse(response); } } @Nested class TestExtractResourceIdFromLocationHeader { private final String resourceId = GroupRepresentationTestFactory.create().getId(); private final String location = "https://keycloak-url.test/admin/realms/test/groups/" + resourceId; @Test void shouldReturnId() { var id = service.extractResourceIdFromLocationHeader(location); assertThat(id).isEqualTo(resourceId); } } }