테스트 코드를 왜 써야하는가  

잘못된 인식

  • 테스트 = 귀찮은 추가 작업
  • 테스트 = 커버리지 숫자 맞추기
  • 테스트 = 모든 메서드에 assert 붙이기

올바른 인식

  • 테스트는 설계의 결과물
  • 테스트는 의도를 문서화하는 코드
  • 테스트는 미래의 나(또는 팀원)를 살리는 보험

=> 테스트가 쓰기 어렵다면, 설계가 잘못된 경우가 많다

테스트는 책임 단위로 작성

예시:

  • UserService
    • 모든 기능 다 테스트
    • 회원 가입 규칙을 올바르게 처리하는가?

즉, 테스트 이름만 봐도 이 코드는 무엇을 책임지는지 보여야 한다.

 

주의할점 

Controller 테스트는 Service를 신뢰해야 한다

Service 동작까지 검증하면  중복 테스트 + 책임 침범으로 본다 

따라서 약속된 HTTP 상태 코드가 내려오는지만 검증한다 

 

정상 흐름 vs 예외 흐름

구분 설명
Happy Path 정상 입력 → 정상 결과
Edge Case 경계값, null, 빈 값
Error Case 예외 발생, 잘못된 요청

 

정상 흐름이란 : 시스템이 기대하는 조건을 모두 만족했을 때, 의도한 결과가 나오는 경로

@Test
void 회원가입이_정상적으로_성공한다() {
    // given
    SignupRequest req = validRequest();

    // when
    User user = authService.signup(req);

    // then
    assertThat(user.getId()).isNotNull();
}

 

이 테스트의 역할

  • 기본 기능이 살아있는지 확인
  • 리팩토링 후 “최소한 이건 깨지지 않았는지” 보장

하지만 이것만 있으면 테스트의 30%만 한 것이다.

 

예외 흐름이란: 

현실의 입력은 대부분 “정상”이 아님을 생각해야한다.

사용자가 잘못된 값을 입력하거나 네트워크 상태가 끊긴다거나 등.. 이러한 잘못된 상황을 막는것이 백엔드가 해야할일!

 

예외 흐름 종류 1 - 검증 실패 

입력값 자체가 잘못된 경우를 말한다 

 

  • 이메일 형식 오류
  • 비밀번호 길이 부족

 

예외 흐름 종류 2 - 상태 기반 예외

입력은 정상인데, 현재 상태가 허용하지 않는 경우를 말한다 

 

  • 이미 탈퇴한 유저
  • 이미 결제 완료된 주문

예외 흐름 종류 3 - 상태 기반 예외

외부 요인, 인프라 문제를 말한다. 

  • DB저장 실패시 회원가입 롤백되는가 
  • 외부 API 장애

 

이 테스트는 “왜 존재하는가?”

모든 테스트는 질문 하나에 답해야 한다.

“이 테스트가 없으면 어떤 버그를 못 잡을까?”

이 질문에 답 못 하면 의미 없는 테스트일 확률이 높다

 

Mock을 쓴다는 것의 진짜 의미

Mock은 “편의”가 아니라 “경계 설정”이다

Mock을 쓴다는 말은 곧:

 

“나는 이 객체의 내부 구현이 아니라, 역할만 신뢰한다”

 

예시:

  • Service 테스트에서
    • Repository는 Mock
    • 이유: DB 검증이 목적이 아니기 때문

Mock 남용 = 테스트 신뢰도 하락
Mock 부족 = 테스트가 느리고 불안정

 

테스트는 설계 리뷰 도구다

테스트 작성 중 느끼는 감정 의미
세팅이 너무 길다 책임이 많다
Mock이 너무 많다 결합도가 높다
테스트 이름 짓기 어렵다 역할이 모호하다
private 메서드 테스트하고 싶다 구조가 잘못됐다

 

 


JSON

 

json <->Dto 변환시

json에서는 권한을 string으로 전달하더라도

자바 dto에서는 이를 enum타입으로 명시했다면 자동으로 변환해준다 

 

그렇다면 테스트에서 dto-> json으로 변환하는 과정을 거치는 이유가 무엇일까? 

1.dto를 수정했을 때 런타임이 아닌 컴파일 단에서 에러를 잡을 수 있다 

2.json으로 작성했을 경우 까먹고 넘어갈 수 있다 

테스트는 통과할 수도 있음 (실제 API는 깨짐)

 

mockMvc: 가짜 HTTP 요청 보내기

  • 실제 서버를 띄우지 않고
  • Spring MVC DispatcherServlet까지만 실행하는 테스트 도구
mockMvc.perform(post("/api/auth/signup")

 

 

HTTP 헤더 설정

Spring은 이걸 보고:

  • @RequestBody를 무엇으로 파싱할지 결정
  • 여기선 JSON으로 파싱
 .contentType(MediaType.APPLICATION_JSON)

 

DTO 객체 → JSON 문자열 변환 후 HTTP Body에 JSON을 담음

.content(objectMapper.writeValueAsString(signupReqDto)))

 

 

http 요청 결과 형태

POST /api/signup
Content-Type: application/json

{
  "email": "test@test.com",
  "password": "password123",
  "role": "BUYER"
}

 

@MockBean

Spring Boot 3.4.0 버전부터 @MockBean Deprecated

@MockitoBean으로 대체

 

 

 

엄청나게 긴 오류코드를 마주했다 한줄씩 해석해보자

***************************

APPLICATION FAILED TO START

***************************



Description:



Parameter 0 of constructor in com.example.yongeunmarket.jwt.JwtFilter required 

a bean of type 'com.example.yongeunmarket.jwt.JwtTokenProvider' that could not be found.



2025-12-19T17:42:45.669+09:00  WARN 2960 --- [yongeun-market] [    Test worker] o.s.test.context.TestContextManager      : Caught exception while allowing TestExecutionListener [org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener] to prepare test instance [com.example.yongeunmarket.controller.AuthControllerTest@5db0003d]



java.lang.IllegalStateException: Failed to load ApplicationContext for

[WebMergedContextConfiguration ...

org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper=true]



Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jwtFilter' defined in file [/Users/heoarim/sparta/consumer-to-consumer-project/build/classes/java/main/com/example/yongeunmarket/jwt/JwtFilter.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type 'com.example.yongeunmarket.jwt.JwtTokenProvider' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:804) ~[spring-beans-6.2.14.jar:6.2.14]



... 생략
  • JwtFilter 클래스가 문제다 JwtTokenProvider 주입받으려다 실패했다 왜? Bean이 없다
  • 스프링의 핵심 컨테이너인 ApplicationContext를 로드하는데 실패했다 

여기서 알아야할 것은 컨트롤러 테스트를 하고있는데 스프링을 띄우다가 실패했다는 것이다

'TIL' 카테고리의 다른 글

TIL/ 260112  (0) 2026.01.13
TIL/251222  (0) 2025.12.22
TIL/ 연관관계 매핑  (0) 2025.10.21
TIL / RESTful API  (0) 2025.10.17

+ Recent posts