Skip to content

Commit 8e7614d

Browse files
committed
Test: 컨트롤러 테스트 작성 및 개선
1 parent 955f4f4 commit 8e7614d

File tree

5 files changed

+196
-5
lines changed

5 files changed

+196
-5
lines changed

src/main/java/com/back/domain/user/controller/AuthController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import io.swagger.v3.oas.annotations.Operation;
88
import io.swagger.v3.oas.annotations.responses.ApiResponse;
99
import io.swagger.v3.oas.annotations.responses.ApiResponses;
10+
import jakarta.validation.Valid;
1011
import lombok.RequiredArgsConstructor;
1112
import org.springframework.http.HttpStatus;
1213
import org.springframework.http.ResponseEntity;
@@ -33,7 +34,7 @@ public class AuthController {
3334
@ApiResponse(responseCode = "500", description = "서버 내부 오류")
3435
})
3536
public ResponseEntity<RsData<UserResponse>> register(
36-
@RequestBody UserRegisterRequest request
37+
@Valid @RequestBody UserRegisterRequest request
3738
) {
3839
UserResponse response = userService.register(request);
3940
return ResponseEntity

src/main/java/com/back/domain/user/repository/UserRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
import org.springframework.data.jpa.repository.JpaRepository;
55
import org.springframework.stereotype.Repository;
66

7+
import java.util.Optional;
8+
79
@Repository
810
public interface UserRepository extends JpaRepository<User, Long> {
911
boolean existsByUsername(String username);
1012
boolean existsByEmail(String email);
13+
Optional<User> findByUsername(String username);
1114
}

src/main/java/com/back/global/exception/ErrorCode.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ public enum ErrorCode {
1010

1111
// ======================== 사용자 관련 ========================
1212
USER_NOT_FOUND(HttpStatus.NOT_FOUND, "USER_001", "존재하지 않는 사용자입니다."),
13-
USERNAME_DUPLICATED(HttpStatus.CONFLICT, "USER_409", "이미 사용 중인 아이디입니다."),
14-
EMAIL_DUPLICATED(HttpStatus.CONFLICT, "USER_409", "이미 사용 중인 이메일입니다."),
15-
NICKNAME_DUPLICATED(HttpStatus.CONFLICT, "USER_409", "이미 사용 중인 닉네임입니다."),
16-
INVALID_PASSWORD(HttpStatus.BAD_REQUEST, "USER_400", "비밀번호는 최소 8자 이상, 숫자/특수문자를 포함해야 합니다."),
13+
USERNAME_DUPLICATED(HttpStatus.CONFLICT, "USER_002", "이미 사용 중인 아이디입니다."),
14+
EMAIL_DUPLICATED(HttpStatus.CONFLICT, "USER_003", "이미 사용 중인 이메일입니다."),
15+
NICKNAME_DUPLICATED(HttpStatus.CONFLICT, "USER_004", "이미 사용 중인 닉네임입니다."),
16+
INVALID_PASSWORD(HttpStatus.BAD_REQUEST, "USER_005", "비밀번호는 최소 8자 이상, 숫자/특수문자를 포함해야 합니다."),
1717

1818
// ======================== 스터디룸 관련 ========================
1919
ROOM_NOT_FOUND(HttpStatus.NOT_FOUND, "ROOM_001", "존재하지 않는 방입니다."),

src/main/java/com/back/global/exception/GlobalExceptionHandler.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package com.back.global.exception;
22

33
import com.back.global.common.dto.RsData;
4+
import org.springframework.http.HttpStatus;
45
import org.springframework.http.ResponseEntity;
6+
import org.springframework.web.bind.MethodArgumentNotValidException;
57
import org.springframework.web.bind.annotation.ExceptionHandler;
68
import org.springframework.web.bind.annotation.RestControllerAdvice;
79

@@ -17,4 +19,11 @@ public ResponseEntity<RsData<Void>> handleCustomException(
1719
.status(errorCode.getStatus())
1820
.body(RsData.fail(errorCode));
1921
}
22+
23+
@ExceptionHandler(MethodArgumentNotValidException.class)
24+
public ResponseEntity<RsData<Void>> handleValidationException(MethodArgumentNotValidException ex) {
25+
return ResponseEntity
26+
.status(HttpStatus.BAD_REQUEST)
27+
.body(RsData.fail(ErrorCode.BAD_REQUEST));
28+
}
2029
}
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package com.back.domain.user.controller;
2+
3+
import com.back.domain.user.entity.User;
4+
import com.back.domain.user.entity.UserProfile;
5+
import com.back.domain.user.entity.UserStatus;
6+
import com.back.domain.user.repository.UserRepository;
7+
import org.junit.jupiter.api.DisplayName;
8+
import org.junit.jupiter.api.Test;
9+
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
11+
import org.springframework.boot.test.context.SpringBootTest;
12+
import org.springframework.http.MediaType;
13+
import org.springframework.test.context.ActiveProfiles;
14+
import org.springframework.test.web.servlet.MockMvc;
15+
import org.springframework.test.web.servlet.ResultActions;
16+
import org.springframework.transaction.annotation.Transactional;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
20+
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
21+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
22+
23+
@SpringBootTest
24+
@AutoConfigureMockMvc
25+
@ActiveProfiles("test")
26+
@Transactional
27+
class AuthControllerTest {
28+
29+
@Autowired
30+
private MockMvc mvc;
31+
32+
@Autowired
33+
private UserRepository userRepository;
34+
35+
@Test
36+
@DisplayName("정상 회원가입 → 201 Created")
37+
void register_success() throws Exception {
38+
// given
39+
String body = """
40+
{
41+
"username": "testuser",
42+
"email": "[email protected]",
43+
"password": "P@ssw0rd!",
44+
"nickname": "홍길동"
45+
}
46+
""";
47+
48+
// when
49+
ResultActions resultActions = mvc.perform(
50+
post("/api/auth/register")
51+
.contentType(MediaType.APPLICATION_JSON)
52+
.content(body)
53+
).andDo(print());
54+
55+
// then
56+
resultActions
57+
.andExpect(status().isCreated())
58+
.andExpect(jsonPath("$.success").value(true))
59+
.andExpect(jsonPath("$.data.username").value("testuser"))
60+
.andExpect(jsonPath("$.data.email").value("[email protected]"))
61+
.andExpect(jsonPath("$.data.nickname").value("홍길동"));
62+
63+
User saved = userRepository.findByUsername("testuser").orElseThrow();
64+
assertThat(saved.getUserStatus()).isEqualTo(UserStatus.PENDING);
65+
}
66+
67+
@Test
68+
@DisplayName("중복 username → 409 Conflict")
69+
void register_duplicateUsername() throws Exception {
70+
User existing = User.createUser("dupuser", "[email protected]", "password123!");
71+
existing.setUserProfile(new UserProfile(existing, "dupnick", null, null, null, 0));
72+
userRepository.save(existing);
73+
74+
String body = """
75+
{
76+
"username": "dupuser",
77+
"email": "[email protected]",
78+
"password": "P@ssw0rd!",
79+
"nickname": "다른닉네임"
80+
}
81+
""";
82+
83+
mvc.perform(post("/api/auth/register")
84+
.contentType(MediaType.APPLICATION_JSON)
85+
.content(body))
86+
.andDo(print())
87+
.andExpect(status().isConflict())
88+
.andExpect(jsonPath("$.code").value("USER_002"));
89+
}
90+
91+
@Test
92+
@DisplayName("중복 email → 409 Conflict")
93+
void register_duplicateEmail() throws Exception {
94+
User existing = User.createUser("user1", "[email protected]", "password123!");
95+
existing.setUserProfile(new UserProfile(existing, "nick1", null, null, null, 0));
96+
userRepository.save(existing);
97+
98+
String body = """
99+
{
100+
"username": "otheruser",
101+
"email": "[email protected]",
102+
"password": "P@ssw0rd!",
103+
"nickname": "다른닉네임"
104+
}
105+
""";
106+
107+
mvc.perform(post("/api/auth/register")
108+
.contentType(MediaType.APPLICATION_JSON)
109+
.content(body))
110+
.andDo(print())
111+
.andExpect(status().isConflict())
112+
.andExpect(jsonPath("$.code").value("USER_003"));
113+
}
114+
115+
@Test
116+
@DisplayName("중복 nickname → 409 Conflict")
117+
void register_duplicateNickname() throws Exception {
118+
User existing = User.createUser("user2", "[email protected]", "password123!");
119+
existing.setUserProfile(new UserProfile(existing, "dupnick", null, null, null, 0));
120+
userRepository.save(existing);
121+
122+
String body = """
123+
{
124+
"username": "newuser",
125+
"email": "[email protected]",
126+
"password": "P@ssw0rd!",
127+
"nickname": "dupnick"
128+
}
129+
""";
130+
131+
mvc.perform(post("/api/auth/register")
132+
.contentType(MediaType.APPLICATION_JSON)
133+
.content(body))
134+
.andDo(print())
135+
.andExpect(status().isConflict())
136+
.andExpect(jsonPath("$.code").value("USER_004"));
137+
}
138+
139+
@Test
140+
@DisplayName("비밀번호 정책 위반 → 400 Bad Request")
141+
void register_invalidPassword() throws Exception {
142+
String body = """
143+
{
144+
"username": "weakpw",
145+
"email": "[email protected]",
146+
"password": "password",
147+
"nickname": "닉네임"
148+
}
149+
""";
150+
151+
mvc.perform(post("/api/auth/register")
152+
.contentType(MediaType.APPLICATION_JSON)
153+
.content(body))
154+
.andDo(print())
155+
.andExpect(status().isBadRequest())
156+
.andExpect(jsonPath("$.code").value("USER_005"));
157+
}
158+
159+
@Test
160+
@DisplayName("잘못된 요청값 (필수 필드 누락) → 400 Bad Request")
161+
void register_invalidRequest_missingField() throws Exception {
162+
String body = """
163+
{
164+
"username": "",
165+
"email": "invalid",
166+
"password": "",
167+
"nickname": ""
168+
}
169+
""";
170+
171+
mvc.perform(post("/api/auth/register")
172+
.contentType(MediaType.APPLICATION_JSON)
173+
.content(body))
174+
.andDo(print())
175+
.andExpect(status().isBadRequest())
176+
.andExpect(jsonPath("$.code").value("COMMON_400"));
177+
}
178+
}

0 commit comments

Comments
 (0)