38강과 39강에서는 새로운 기능을 추가하지 않는다.
대신 이미 구현된 인증/인가 로직을 테스트로 단단히 고정한다.
두 강의의 성격이 거의 동일하기 때문에,
이번 글에서는 38강 + 39강을 한 번에 정리한다.
이번 두 강의의 공통 주제는 명확하다.
“권한 체크는 반드시 테스트로 보장해야 한다.”
추가된 테스트는 전부 다음 범주에 속한다.
38강에서는 글 쓰기 / 글 수정 / 글 삭제에 대해
인증·권한 테스트가 추가된다.
@Test
@DisplayName("글 쓰기, with wrong authorization header")
void t11() throws Exception {
mvc.perform(
post("/api/v1/posts")
.header("Authorization", "Bearer wrong-api-key")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": "제목",
"content": "내용"
}
""")
)
.andExpect(status().isUnauthorized())
.andExpect(jsonPath("$.resultCode").value("401-3"))
.andExpect(jsonPath("$.msg").value("API 키가 유효하지 않습니다."));
}
👉 인증 실패(401) 가 정확히 발생하는지 검증한다.
@Test
@DisplayName("글 수정, without permission")
void t12() throws Exception {
mvc.perform(
put("/api/v1/posts/1")
.header("Authorization", "Bearer user3-api-key")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"title": "제목 new",
"content": "내용 new"
}
""")
)
.andExpect(status().isForbidden())
.andExpect(jsonPath("$.resultCode").value("403-1"))
.andExpect(jsonPath("$.msg").value("1번 글 수정권한이 없습니다."));
}
👉 인가 실패(403) 를 테스트로 고정한다.
@Test
@DisplayName("글 삭제, without permission")
void t13() throws Exception {
mvc.perform(
delete("/api/v1/posts/1")
.header("Authorization", "Bearer user3-api-key")
)
.andExpect(status().isForbidden())
.andExpect(jsonPath("$.resultCode").value("403-2"))
.andExpect(jsonPath("$.msg").value("1번 글 삭제권한이 없습니다."));
}
39강에서는 동일한 패턴을 댓글 도메인에 그대로 적용한다.
@Test
@DisplayName("댓글 수정, without permission")
void t6() throws Exception {
mvc.perform(
put("/api/v1/posts/1/comments/1")
.header("Authorization", "Bearer user3-api-key")
.contentType(MediaType.APPLICATION_JSON)
.content("""
{
"content": "내용 new"
}
""")
)
.andExpect(status().isForbidden())
.andExpect(jsonPath("$.resultCode").value("403-1"))
.andExpect(jsonPath("$.msg").value("1번 댓글 수정권한이 없습니다."));
}
@Test
@DisplayName("댓글 삭제, without permission")
void t7() throws Exception {
mvc.perform(
delete("/api/v1/posts/1/comments/1")
.header("Authorization", "Bearer user3-api-key")
)
.andExpect(status().isForbidden())
.andExpect(jsonPath("$.resultCode").value("403-2"))
.andExpect(jsonPath("$.msg").value("1번 댓글 삭제권한이 없습니다."));
}
강의에서 계속 강조되는 이유가 있다.
@Valid, @NotBlank, @Size👉 상대적으로 테스트 우선순위가 낮다.
👉 테스트가 없으면 위험하다.
이 테스트들은 단순히 “에러가 난다”를 확인하는 게 아니다.
다음을 명확하게 보장한다.
👉 권한 정책이 테스트로 문서화된 셈이다.
36강에서 했던 작업을 떠올려보자.
checkActorCanModify, checkActorCanDelete 도입이번 38~39강 테스트는
“이 엔티티 권한 로직이 실제로 제대로 동작하는가?”
를 검증하는 단계다.
지금 구조는 다음 순서로 완성된다.
👉 보안 규칙이 코드 + 테스트로 이중 보호된다.
이번 강의들의 핵심은 이 문장으로 정리된다.
“권한 로직은 믿지 말고, 테스트로 증명하자.”