공공부하자개발 · 영어 학습 노트
자바
실무 확장Excel · 파일 업로드 · DB 연동0/22 완료
  • 01Excel(XLSX) 구조와 순수 JDK로 읽기/쓰기
  • 02Apache POI로 Excel 업로드/다운로드
  • 03파일 업로드/다운로드 서버 (HttpServer)
  • 04JDBC 기초와 트랜잭션 (H2)
  • 05MyBatis 어노테이션 매퍼로 쿼리 연동
  • 06MyBatis XML 매퍼 · Oracle 방언 · PageHelper · Spring Boot
  • 07REST API 서버와 JSON
  • 08Vue 3 SPA 와 Java 서버 연동
  • 09@Scheduled 운영
  • 10로깅 실무: 레벨·계층, MDC 추적, 예외·성능, 마스킹, 롤링, JSON 로그
  • 11외부 API 연동
  • 12테스트 실무
  • 13암호화·개인정보 보호
  • 14인코딩·한글 실무
  • 15@Transactional 심화
  • 16긴 작업 비동기 처리와 진행률
  • 17SFTP·FTP 파일 연계
  • 18로컬 캐시와 @Cacheable
  • 19메일·알림 발송
  • 20웹 보안 체크리스트
  • 21빌드 도구와 폐쇄망 의존성 반입
  • 22성능 측정: p50·p95·p99, 측정 계층, JFR, JMH 함정, 자체 부하 테스트, 병목 순위
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 실무 확장 › 12 / 22

테스트 실무

JUnit 5 단위·통합 테스트, 테스트 더블, 시계 제어, H2 롤백
섹션 7진행 0 / 22
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

5. 자주 하는 실수 (Tip)

❌ 실수 1: 테스트 안에서 LocalDateTime.now() 를 직접 쓴다

밤 10시가 넘으면 영업시간 검증 테스트가 갑자기 깨집니다. 원인은 실제 현재 시각을 쓴 것이고, 해결은 Clock 을 주입받아 Clock.fixed 로 고정하는 것입니다. CI 서버의 시간대가 달라도 결과가 항상 같아집니다.

❌ 실수 2: 테스트 순서에 의존한다

static 필드에 상태를 쌓거나, 앞 테스트가 커밋한 행을 다음 테스트가 전제로 삼으면 실행 순서를 바꾸는 순간 깨집니다. @BeforeEach 로 매번 새로 만들고, DB 는 트랜잭션 롤백으로 격리해야 합니다. JUnit 은 기본적으로 순서를 보장하지 않습니다.

❌ 실수 3: 단정문 없는 테스트

@Test 안에서 값을 출력만 하고 assert 가 하나도 없으면, 예외만 안 터지면 항상 초록불입니다. 로직이 완전히 잘못돼도 잡히지 않습니다. 확인하려는 값마다 최소 하나의 assertEquals/assertTrue 가 있어야 합니다.

❌ 실수 4: 한 테스트에 시나리오 5개를 몰아넣는다

정상·실패·경계·예외를 한 메서드에 다 넣으면 하나가 깨졌을 때 나머지 검증까지 실행이 멈춰 원인이 뭔지 알기 어렵습니다. 시나리오마다 메서드를 나누거나, 경계값은 @ParameterizedTest 로 뽑아냅니다.

❌ 실수 5: 목을 너무 많이 써서 구현을 그대로 베낀 테스트

verify(repo).save(any()), verify(repo, times(3)).findById(any()) 를 줄줄이 나열하면 테스트가 구현 순서를 그대로 따라간 것뿐입니다. 구현을 리팩터링만 해도 테스트가 깨집니다. 결과 상태를 검증하는 편이 대부분 더 안전합니다.

❌ 실수 6: 운영 DB 에 붙여 테스트한다

테스트가 실행될 때마다 운영 데이터가 바뀌거나, 동시에 돌리면 서로 데이터를 덮어씁니다. H2 메모리 DB 로 스키마를 똑같이 맞추고, 트랜잭션 롤백으로 격리해야 안전합니다.

❌ 실수 7: BigDecimal.equals 로 비교한다

java
assertEquals(new BigDecimal("1000"), new BigDecimal("1000.00"));   // 실패! 스케일이 다름

equals 는 값이 같아도 스케일이 다르면 false 를 돌려줍니다. assertEquals(0, a.compareTo(b)) 로 비교하거나 assertThat(a).isEqualByComparingTo(b) 를 씁니다.

❌ 실수 8: 예외 테스트를 try-catch + fail 로 쓴다

java
try { service.place("kim", BigDecimal.ZERO); fail("예외가 나야 함"); }
catch (IllegalArgumentException e) { /* ok */ }

assertThrows 한 줄이면 되는데 4줄로 늘어나고, 다른 예외가 나도 통과해 버릴 수 있습니다. assertThrows(IllegalArgumentException.class, () -> ...) 로 바꿉니다.

❌ 실수 9: private 메서드를 테스트하려 한다

리플렉션으로 private 메서드를 억지로 호출하는 코드는 구현이 바뀌면 바로 깨집니다. discountFor 처럼 순수 로직은 static 이나 별도 클래스로 빼서 public 으로 두면, 억지 없이 테스트할 수 있습니다.

❌ 실수 10: @SpringBootTest 를 모든 테스트에 붙인다

컨텍스트 전체를 매번 새로 띄우면 테스트 하나에 수 초가 걸립니다. 순수 로직은 OrderServiceTest 처럼 컨텍스트 없이, DB 접근만 @MybatisTest/@JdbcTest 로, 전체 배선 확인은 소수의 @SpringBootTest 로 나눕니다.

자주 하는 실수 (Tip)
  • ❌ 실수 1: 테스트 안에서 LocalDateTime.now() 를 직접 쓴다
  • ❌ 실수 2: 테스트 순서에 의존한다
  • ❌ 실수 3: 단정문 없는 테스트
  • ❌ 실수 4: 한 테스트에 시나리오 5개를 몰아넣는다
  • ❌ 실수 5: 목을 너무 많이 써서 구현을 그대로 베낀 테스트
  • ❌ 실수 6: 운영 DB 에 붙여 테스트한다
  • ❌ 실수 7: BigDecimal.equals 로 비교한다
  • ❌ 실수 8: 예외 테스트를 try-catch + fail 로 쓴다
  • ❌ 실수 9: private 메서드를 테스트하려 한다
  • ❌ 실수 10: @SpringBootTest 를 모든 테스트에 붙인다
이전 섹션4 응용 변형 예제5 / 7다음 섹션6 연습 문제