fix(stammbaum): structured error codes in RelationshipController

getRelationshipBetween now throws DomainException with RELATIONSHIP_NOT_FOUND
instead of ResponseStatusException, so the frontend receives a typed error code.
Removed redundant validateRelationType() guard — RelationshipService.parseType()
already handles this with the same DomainException/VALIDATION_ERROR path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-28 10:19:09 +02:00
committed by marcel
parent 7a3d919c2d
commit 22752ac1ae
2 changed files with 61 additions and 15 deletions

View File

@@ -0,0 +1,57 @@
package org.raddatz.familienarchiv.relationship;
import org.junit.jupiter.api.Test;
import org.raddatz.familienarchiv.config.SecurityConfig;
import org.raddatz.familienarchiv.exception.ErrorCode;
import org.raddatz.familienarchiv.security.PermissionAspect;
import org.raddatz.familienarchiv.service.CustomUserDetailsService;
import org.raddatz.familienarchiv.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.http.MediaType;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Optional;
import java.util.UUID;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(RelationshipController.class)
@Import({SecurityConfig.class, PermissionAspect.class, AopAutoConfiguration.class})
class RelationshipControllerTest {
@Autowired MockMvc mockMvc;
@MockitoBean RelationshipService relationshipService;
@MockitoBean UserService userService;
@MockitoBean CustomUserDetailsService customUserDetailsService;
private static final UUID PERSON_ID = UUID.randomUUID();
private static final UUID OTHER_ID = UUID.randomUUID();
@Test
@WithMockUser(username = "testuser", authorities = {"READ_ALL"})
void getRelationshipBetween_returns404_with_RELATIONSHIP_NOT_FOUND_code_when_no_path() throws Exception {
when(relationshipService.getRelationshipBetween(any(), any())).thenReturn(Optional.empty());
mockMvc.perform(get("/api/persons/{aId}/relationship-to/{bId}", PERSON_ID, OTHER_ID))
.andExpect(status().isNotFound())
.andExpect(jsonPath("$.code").value(ErrorCode.RELATIONSHIP_NOT_FOUND.name()));
}
@Test
@WithMockUser(username = "testuser", authorities = {"READ_ALL"})
void addRelationship_returns403_for_user_with_READ_ALL_only() throws Exception {
mockMvc.perform(post("/api/persons/{id}/relationships", PERSON_ID)
.contentType(MediaType.APPLICATION_JSON)
.content("{\"relatedPersonId\":\"" + OTHER_ID + "\",\"relationType\":\"PARENT_OF\"}"))
.andExpect(status().isForbidden());
}
}