목록2024/01 (27)
쌓고 쌓다
"/members/signup" 컨트롤러 테스트 코드 실행시 401 에러를 응답으로 준다... 이 매핑은 permitAll()을 해두었는데도 말이다. 원인은 @WebMvcTest 어노테이션에 있었다. 기본적으로 @Test 어노테이션이 붙는다면 Spring Security를 auto-configure한다고 되어 있다. @SpringBootTest와 달리 @WebMvcTest는 해당 컨트롤러 동작에 필요한 빈들만 등록하여 사용하기에 시큐리티는 제외되는것 같다. defaultSecurityFilterChain에 보면 모든 요청에 인증이 필요한게 기본 값이다. 그래서 Spring Security는 기본 설정으로 등록되기에 해당 매핑은 인증, 인가가 필요한 것이다. @WithMockUser를 통해 테스트시 필요한..
Response Body에 값이 담겨 있지 않는 문제가 발생했다. 컨트롤러 코드는 다음과 같았다. memberService에 addMember를 통해 반환된 MemberResponse를 body 응답으로 보낸다. 테스트 코드에 given을 사용하여 다음과 같이 signUpMember이 들어왔을때 memberResponse를 반환하도록 했다. /* SignUpMember signUpMember = new SignUpMember(); signUpMember.setName("새로운닉네임"); signUpMember.setLoginId("새로운아이디"); signUpMember.setLoginPwd("새로운비밀번호"); MemberResponse memberResponse = new MemberResponse(..
JPA를 사용하여 페이징 처리된 데이터를 응답 해보자. 먼저, 다음과 같은 URL로 API를 만들고자 한다. /locations/{locationId}/posters?page={페이지번호}&size={페이지크기}sort={정렬방법} page, size, sort의 값은 필수가 아니며 입력하지 않은 값에대해 기본 값을 설정할 예정이다. locationId를 포함하는 poster들을 반환해주는 API이다. 컨트롤러로 들어온 요청의 쿼리파라미터를 처리할 클래스를 다음과 같이 하나 만들어 보자. PosterPageRequest package com.example.spotserver.dto.request; import jakarta.validation.constraints.Max; import jakarta.va..
이상하게 컨트롤러에서 처리하지 못할 요청에 대해 404 에러가 안뜨고 401 에러가 뜨는 것이다. Controller에서 매핑하지 않은 요청에 대해 404 NOT FOUND 에러가 안뜨고 내가 예외 처리한 401 에러가 뜬다..! 왜일까? 결론은 스프링부트에서 에러 처리시 Forward인지.. Redirect인지.. 어떤 방식으로 /error로 요청을 보낸다. /error 매핑에서 에러를 처리하여 다음과 같이 JSON 또는 HTML로 응답을 내려주는것이다. 그렇다 현재 /error에 대해서도 Authentication이 적용되기 때문에 인증이 필요하다고 401 에러가 뜨는 것이다. 그런데 GET 요청은 모두 permitAll을 해두었지만 이상하게 401 에러가 뜨긴뜬다... 의문! 보니깐 직접 /err..
API를 작성하고 매번 POSTMAN으로 요청과 응답을 확인해보는 과정은 시간도 많이 들고 번거롭다. 어떤 코드의 수정이나 추가가 일어났을때 모든 시스템의 API가 정상적으로 돌아가는지 확인하기 위해 테스트 코드를 작성해보자. MockMvc를 설정하고 초기화 시키는 코드는 다음과 같다. @SpringBootTest @Transactional @TestInstance(TestInstance.Lifecycle.PER_CLASS) class MemberControllerTest { private MockMvc mockMvc; @Autowired private WebApplicationContext webApplicationContext; @BeforeAll public void beforeAll() throw..
테스트 코드를 작성하며 초기 데이터가 필요하여 생성하여 디비에 저장하고 테스트가 끝난후 삭제하는 과정이 필요했다. 쉽게 말해서 테스트 코드를 실행하기 전과 후에 딱 한번 실행할 함수가 필요했다. 거기에 좋은 @BeforeAll, @AfterAll 어노테이션이 있어 사용하려고 한다. 그러나 이 어노테이션들은 static 메서드에 붙이고 사용해야 했다. 왜 static 이여야할까...? JUnit5에서 테스트 클래스의 Life Cycle은 기본값이 PER_METHOD이다. 즉, 테스트 클래스는 하나의 테스트 메서드가 끝나고 다시 클래스가 생성된다. 그래서 static으로 선언해야지 클래스 내부 요소들을 유지할 수 있는 것이다. 다음과 같이 테스트 클래스의 Life Cycle을 클래스단위로 바꿔주자. 다음은 ..
다른 친구가 앱을 만들고 나는 API 서버를 구축하고 있는데 친구가 API 요청시 정상적인 응답을 못주는 상황을 발견했다. 서버에서 요청을 처리하는 코드는 다음과 같다. @PostMapping(value = "/locations/{locationId}/posters") public ResponseEntity addPoster(@Valid @RequestPart PosterRequest posterRequest, @RequestPart(required = false) List files, @PathVariable Long locationId, @AuthenticationPrincipal(expression = "member") Member member) throws IOException {...} Mult..
시큐리티 설정을 통해 인증, 인가 설정을 할 수 있다. 이제 이 인증, 인가에 실패했을 경우에 JSON 예외 응답을 보내보자. SecurityConfig.java http.exceptionHandling(e -> e .authenticationEntryPoint(new JwtAuthenticationEntryPoint()) .accessDeniedHandler(new JwtAccessDenyHandler())); exceptionHandling을 통해 예외를 처리할 로직은 시큐리티에 등록할 수 있다. 인증 예외는 AuthenticationEntryPoint 인터페이스를 구현하여 등록할 수 있고 인가 예외는 AccessDeniedHandler 인터페이스를 구현하여 등록할 수 있다. 먼저 Enum 타입으로 ..