Skip to content

Commit 5094d67

Browse files
committed
test: GlobalExceptionHandler 테스트 구현
1 parent 412cd75 commit 5094d67

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package eatda.exception;
2+
3+
4+
import static org.hamcrest.Matchers.equalTo;
5+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
6+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
7+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
8+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
9+
10+
import eatda.config.CorsConfig;
11+
import eatda.config.CorsProperties;
12+
import eatda.config.WebConfig;
13+
import org.junit.jupiter.api.Nested;
14+
import org.junit.jupiter.api.Test;
15+
import org.springframework.beans.factory.annotation.Autowired;
16+
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
17+
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
18+
import org.springframework.boot.test.context.TestConfiguration;
19+
import org.springframework.context.annotation.Bean;
20+
import org.springframework.context.annotation.ComponentScan;
21+
import org.springframework.context.annotation.FilterType;
22+
import org.springframework.context.annotation.Import;
23+
import org.springframework.http.MediaType;
24+
import org.springframework.test.context.ActiveProfiles;
25+
import org.springframework.test.web.servlet.MockMvc;
26+
import org.springframework.web.bind.annotation.GetMapping;
27+
import org.springframework.web.bind.annotation.PostMapping;
28+
import org.springframework.web.bind.annotation.RequestHeader;
29+
import org.springframework.web.bind.annotation.RequestMapping;
30+
import org.springframework.web.bind.annotation.RequestParam;
31+
import org.springframework.web.bind.annotation.RestController;
32+
33+
@WebMvcTest(
34+
controllers = GlobalExceptionHandlerTest.TestExceptionController.class,
35+
excludeAutoConfiguration = SecurityAutoConfiguration.class,
36+
excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {
37+
WebConfig.class, CorsConfig.class
38+
})
39+
)
40+
@Import(GlobalExceptionHandler.class)
41+
@ActiveProfiles("local")
42+
class GlobalExceptionHandlerTest {
43+
44+
@TestConfiguration
45+
static class TestCorsConfig {
46+
@Bean
47+
public CorsProperties corsProperties() {
48+
return new CorsProperties();
49+
}
50+
}
51+
52+
@RestController
53+
@RequestMapping("/test")
54+
public static class TestExceptionController {
55+
56+
@GetMapping("/business")
57+
public void throwBusinessException() {
58+
throw new BusinessException(BusinessErrorCode.STORY_NOT_FOUND);
59+
}
60+
61+
@GetMapping("/mismatch")
62+
public void typeMismatch(@RequestParam Long id) {
63+
}
64+
65+
@GetMapping("/header")
66+
public void missingHeader(@RequestHeader("X-Request-Id") String header) {
67+
}
68+
69+
@PostMapping(value = "/mediatype", consumes = MediaType.APPLICATION_JSON_VALUE)
70+
public void mediaTypeTest() {
71+
}
72+
73+
@GetMapping("/method")
74+
public void allowedMethod() {
75+
}
76+
77+
@GetMapping("/unexpected")
78+
public void throwUnexpected() {
79+
throw new RuntimeException("예상치 못한 예외");
80+
}
81+
}
82+
83+
@Autowired
84+
private MockMvc mockMvc;
85+
86+
@Nested
87+
class handExceptions {
88+
89+
@Test
90+
void 비즈니스_예외는_정의된_코드로_응답된다() throws Exception {
91+
mockMvc.perform(get("/test/business"))
92+
.andExpect(status().isNotFound())
93+
.andExpect(jsonPath("$.errorCode", equalTo(BusinessErrorCode.STORY_NOT_FOUND.getCode())))
94+
.andExpect(jsonPath("$.message", equalTo(BusinessErrorCode.STORY_NOT_FOUND.getMessage())));
95+
}
96+
97+
@Test
98+
void 지원하지_않는_HTTP_METHOD는_405() throws Exception {
99+
mockMvc.perform(post("/test/method"))
100+
.andExpect(status().isMethodNotAllowed())
101+
.andExpect(jsonPath("$.errorCode", equalTo(EtcErrorCode.METHOD_NOT_SUPPORTED.getCode())));
102+
}
103+
104+
@Test
105+
void 쿼리파라미터_형변환_실패는_400() throws Exception {
106+
mockMvc.perform(get("/test/mismatch?id=abc"))
107+
.andExpect(status().isBadRequest())
108+
.andExpect(jsonPath("$.errorCode", equalTo(EtcErrorCode.METHOD_ARGUMENT_TYPE_MISMATCH.getCode())));
109+
}
110+
111+
@Test
112+
void 누락된_헤더는_400() throws Exception {
113+
mockMvc.perform(get("/test/header"))
114+
.andExpect(status().isBadRequest())
115+
.andExpect(jsonPath("$.errorCode", equalTo(EtcErrorCode.NO_HEADER_FOUND.getCode())));
116+
}
117+
118+
@Test
119+
void 미지원_MediaType은_415() throws Exception {
120+
mockMvc.perform(post("/test/mediatype")
121+
.contentType(MediaType.APPLICATION_XML))
122+
.andExpect(status().isUnsupportedMediaType())
123+
.andExpect(jsonPath("$.errorCode", equalTo(EtcErrorCode.MEDIA_TYPE_NOT_SUPPORTED.getCode())));
124+
}
125+
126+
@Test
127+
void 처리되지_않은_예외는_500() throws Exception {
128+
mockMvc.perform(get("/test/unexpected"))
129+
.andExpect(status().isInternalServerError())
130+
.andExpect(jsonPath("$.errorCode", equalTo(EtcErrorCode.INTERNAL_SERVER_ERROR.getCode())));
131+
}
132+
}
133+
}

0 commit comments

Comments
 (0)