Test시, MockMvc 요청의 403Error
@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
public class LoginServiceTest {
private static final Logger log = LoggerFactory.getLogger(CharacterServiceTest.class);
@Autowired
MockMvc mockMvc;
@Autowired
ObjectMapper objectMapper;
@Test
void InvalidPassword__sholud_pass_with_error_result() throws Exception {
LoginInpVo inpVo = new LoginInpVo();
inpVo.setEmail("donghyeondev@gmail.com");
inpVo.setPassword("test123");
mockMvc.perform(post("/login")
.header("Origin","*")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(inpVo))
)
.andDo(print());
}
이와 같이 메서드 단위테스트를 진행했다.
원래대로라면 정상적인 통신을 하여 ErrorResult를 뱉어야했다.
하지만 결과는 403에러였다.
MockHttpServletResponse:
Status = 403
Error message = null
Headers = [Content-Type:"text/plain"]
Content type = text/plain
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
생각되는 에러요인은 아래와 같다.
- Spring-Security 의존성을 선언하고 아무런 설정도 없을때
⇒ 이 경우는 나는 아니였다. - ApplicationContext에 Filter가 들어가있는데 잘못되있을때
⇒ 이 경우는@AutoConfigureMockMvc
의addFilter
속성을False
로 주면 해결가능
CORS FIlter에서 Origin을 *
로 처리하고 호출하면 정상적이긴 하다.
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
// .allowedOrigins("http://localhost:3000", "http://localhost:3030", "http://localhost:5000", "http://host.docker.internal:9090");
.allowedOrigin("*")
}
하지만 모든 origin에 대해서 접근을 허용한다는건 그만큼 보안이 약해진다는것을 의미하고, 다른 방법을 찾아야한다.
실질적으로 헤더에 Origin : *
와 같은 속성을 주는게 맞는가에 대한 고민이 생겼다.
당연하게도 Swagger에서 테스트를 했을때는 정확하게 Origin이 들어가 있었다.
cors필터에 .allowedOrigin()
, mockMvc Header
에 스프링부트 프로젝트의 Origin을 추가해주고 다시 테스트를 진행하였다.
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("http://localhost:8880","http://localhost:3000", "http://localhost:3030", "http://localhost:5000", "http://host.docker.internal:9090");
}
mockMvc.perform(post("/login")
.header("Origin","http://localhost:8880")
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(inpVo))
)
.andDo(print());
결과는 예상과 같이 성공이였다.
하지만 다른 문제가 생기는데 바로 한글 인코딩이 안되는 문제였다.
그 이유는 Response의 Content-Type
이였는데, 스프링 부트 2.2.0 이후부터 Charset
이 빠졌기 때문이다.(해당 프로젝트는 2.4.2를 사용중)
해결방법
// WebConfig에 빈을 추가해주던지
@Bean
public CharacterEncodingFilter characterEncodingFilter(){
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
return characterEncodingFilter;
}
혹은 이 전역설정이 모든 서비스가 아닌 Test시에만 사용된다고 싶다면, 별도로 yaml을 생성하고
# 야믈로 추가.. 나는 야믈이 더 깔끔해서 야믈을 선택함.
server:
port: 8880
servlet:
encoding:
charset: UTF-8
enabled: true
force: true
# 아래방식은 deprecated 됬다고한다.
spring:
http:
encoing:
@TestPropertySource(locations = "classpath:/test-encode.yml)
을 사용하면 된다.
'Debug' 카테고리의 다른 글
[IntelliJ] command line is too long. Shorten command line for... (0) | 2020.09.14 |
---|---|
FCM JSON Encoding (0) | 2020.08.06 |
WebApp Debugging, No device Found (0) | 2020.07.11 |
Fragment 내부의 Button에 대해서는 onClick이 작동하지 않는다. (0) | 2020.07.11 |
(HTTPLog)-Static: isSBSettingEnabled false (0) | 2020.07.11 |