Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
Expand All @@ -11,6 +12,7 @@
import com.und.server.auth.filter.AuthMember;
import com.und.server.member.dto.request.NicknameRequest;
import com.und.server.member.dto.response.MemberResponse;
import com.und.server.member.entity.Member;
import com.und.server.member.service.MemberService;

import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -25,6 +27,15 @@ public class MemberController {

private final MemberService memberService;

@GetMapping("/member/nickname")
public ResponseEntity<String> getNickname(
@Parameter(hidden = true) @AuthMember final Long memberId
) {
final Member member = memberService.findMemberById(memberId);

return ResponseEntity.status(HttpStatus.OK).body(member.getNickname());
}
Comment on lines +30 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

API μ‘λ‹΅μœΌλ‘œ μ›μ‹œ(raw) λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•˜λŠ” 것보닀 JSON 객체λ₯Ό λ°˜ν™˜ν•˜λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€. μ΄λŠ” API의 일관성을 μœ μ§€ν•˜κ³  ν–₯ν›„ ν™•μž₯을 μš©μ΄ν•˜κ²Œ ν•©λ‹ˆλ‹€. 예λ₯Ό λ“€μ–΄, λ‚˜μ€‘μ— λ‹€λ₯Έ ν•„λ“œλ₯Ό μΆ”κ°€ν•΄μ•Ό ν•  경우 ν΄λΌμ΄μ–ΈνŠΈ μ½”λ“œ μˆ˜μ • 없이 μ‰½κ²Œ ν™•μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Map.of()λ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ μ „μš© 응닡 DTO(Data Transfer Object)λ₯Ό μƒμ„±ν•˜μ—¬ JSON 객체둜 λ‹‰λ„€μž„μ„ λ°˜ν™˜ν•˜λ„λ‘ μˆ˜μ •ν•˜λŠ” 것을 μ œμ•ˆν•©λ‹ˆλ‹€. ResponseEntity.ok()λ₯Ό μ‚¬μš©ν•˜λ©΄ μ½”λ“œλ₯Ό 더 κ°„κ²°ν•˜κ²Œ λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ°Έκ³ : μ•„λž˜ μ œμ•ˆμ„ μ μš©ν•˜λ €λ©΄ import java.util.Map; ꡬ문을 μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.

μ˜ˆμ‹œ DTO:

public record NicknameResponse(String nickname) {}
Suggested change
@GetMapping("/member/nickname")
public ResponseEntity<String> getNickname(
@Parameter(hidden = true) @AuthMember final Long memberId
) {
final Member member = memberService.findMemberById(memberId);
return ResponseEntity.status(HttpStatus.OK).body(member.getNickname());
}
@GetMapping("/member/nickname")
public ResponseEntity<Map<String, String>> getNickname(
@Parameter(hidden = true) @AuthMember final Long memberId
) {
final Member member = memberService.findMemberById(memberId);
return ResponseEntity.ok(Map.of("nickname", member.getNickname()));
}


@PatchMapping("/member/nickname")
public ResponseEntity<MemberResponse> updateNickname(
@Parameter(hidden = true) @AuthMember final Long memberId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.und.server.member.controller;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import java.nio.charset.StandardCharsets;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
Expand All @@ -28,6 +31,7 @@
import com.und.server.common.exception.ServerException;
import com.und.server.member.dto.request.NicknameRequest;
import com.und.server.member.dto.response.MemberResponse;
import com.und.server.member.entity.Member;
import com.und.server.member.service.MemberService;

@ExtendWith(MockitoExtension.class)
Expand Down Expand Up @@ -131,6 +135,59 @@ void Given_AuthenticatedUser_When_UpdateNickname_Then_ReturnsOkWithUpdatedInfo()
.andExpect(jsonPath("$.nickname").value(newNickname));
}

@Test
@DisplayName("Fails to get member and returns unauthorized when user is not authenticated")
void Given_UnauthenticatedUser_When_GetMember_Then_ReturnsUnauthorized() throws Exception {
// given
final String url = "/v1/member/nickname";
final AuthErrorResult errorResult = AuthErrorResult.UNAUTHORIZED_ACCESS;

doReturn(true).when(authMemberArgumentResolver).supportsParameter(any());
doThrow(new ServerException(errorResult))
.when(authMemberArgumentResolver).resolveArgument(any(), any(), any(), any());

// when
final ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);

// then
resultActions.andExpect(status().isUnauthorized())
.andExpect(jsonPath("$.code").value(errorResult.name()))
.andExpect(jsonPath("$.message").value(errorResult.getMessage()));
}

@Test
@DisplayName("Succeeds in getting member nickname for an authenticated user")
void Given_AuthenticatedUser_When_GetMember_Then_ReturnsOkWithNickname() throws Exception {
// given
final String url = "/v1/member/nickname";
final Long memberId = 1L;
final String nickname = "Chori";
final Member member = Member.builder()
.id(memberId)
.nickname(nickname)
.build();

doReturn(true).when(authMemberArgumentResolver).supportsParameter(any());
doReturn(memberId).when(authMemberArgumentResolver).resolveArgument(any(), any(), any(), any());
doReturn(member).when(memberService).findMemberById(memberId);

// when
final ResultActions resultActions = mockMvc.perform(
MockMvcRequestBuilders.get(url)
);

// then
final String responseContent = resultActions
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString(StandardCharsets.UTF_8);
assertThat(responseContent).isEqualTo(nickname);
verify(memberService).findMemberById(memberId);
Comment on lines +181 to +188

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

컨트둀러 λ³€κ²½ μ œμ•ˆμ— 맞좰 ν…ŒμŠ€νŠΈ μ½”λ“œλ„ μˆ˜μ •μ΄ ν•„μš”ν•©λ‹ˆλ‹€. getContentAsString()으둜 응닡 본문을 직접 λΉ„κ΅ν•˜λŠ” λŒ€μ‹ , jsonPath()λ₯Ό μ‚¬μš©ν•˜μ—¬ JSON ꡬ쑰와 값을 κ²€μ¦ν•˜λŠ” 것이 더 μ•ˆμ •μ μ΄κ³  가독성이 μ’‹μŠ΅λ‹ˆλ‹€. λ‹€λ₯Έ ν…ŒμŠ€νŠΈμ—μ„œλ„ jsonPath()λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμœΌλ―€λ‘œ 일관성을 μœ μ§€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

		// then
		resultActions.andExpect(status().isOk())
			.andExpect(jsonPath("$.nickname").value(nickname));
		verify(memberService).findMemberById(memberId);

}

@Test
@DisplayName("Fails to delete member and returns unauthorized when user is not authenticated")
void Given_UnauthenticatedUser_When_DeleteMember_Then_ReturnsUnauthorized() throws Exception {
Expand Down
Loading