인프런

의존성과 테스트

date
Jan 20, 2025
slug
test-on-spring-with-architecture-2-6
status
Public
tags
테스트를 추가하고 싶은 개발자들의 오답노트
author
summary
의존성과 테스트의 상관 관계를 알아보자
type
Post
thumbnail
updatedAt
Jan 20, 2025 04:35 AM
category
인프런

📝 강의 정리


💡
테스트를 잘 하려면 의존성 주입과 의존성 역전을 잘 다룰 수 있어야 한다.

AS - IS


// User.java class User { private long lastLoginTimeStamp; public void login() { this.lastLoginTimeStamp = Clock.systemUTC().millis(); } } // main() user.login(); // UserTest @Test public void 로그인_테스트() { // given User user = new User(); // when user.login(); // then assertThat(user.getLastLoginTimeStamp()).isEqualto(???????); }
  • User의 내부 로직을 보면 Clock에 의존적이다.
 

🚨 문제점

  • 하지만 외부에서 user.login() 함수를 호출할 때, User가 Clock에 의존하고 있는지 확인할 수 없다.
  • 로그인 테스트 진행 시, login() 메서드 호출 시점과 결과값 비교 시점이 다르게 되므로 정확한 테스트가 어려워진다
 
💡 테스트를 작성하며 “테스트가 불가능한데..?” 혹은 Mock Framework 없이 테스트 짜는게 불가능하다면 이것이 바로 테스트가 보내는 신호이다.
 

TO-BE


의존성 주입과 의존성 역전으로 해결

notion image
@Getter class User { private long lastLoginTimeStamp; public void login(ClockHolder clockHolder) { this.lastLoginTimeStamp = clockHolder.getMillis(); } } // UserService @Service @RequiredArgsConstructor class UserService { private final ClockHolder clockHolder; public void login(User user) { user.login(clockHolder); } }
  • User → Clock 의 의존성 상태에서
    • User → ClockHolder ← Clock
      ⇒ Clock에서 의존성 역전이 일어남
 

Production 환경과 Test 환경을 구분해줄 수 있다.


notion image
// interface interface ClockHolder { long getMillis(); } // SystemClockHolder // 스프링 빈으로 등록되어 UserService에 주입된다. @Component class SystemClockHoler implements ClockHolder { @Override public long getMillis() { return Clock.systemUTC().millis(); } } // TestClockHolder @AllArgsConstructor class TestClockHolder implements ClockHolder { private Clock clock; @Override public long getMillis() { return clock.millis(); } } // UserServiceTest @Test public void 로그인_테스트() { // given Clock clock = Clock.fixed(~~); User user = new User(); UserService userService = new UserService(new TestClockHolder(clock)); // when userService.login(user); // then assertThat(~~); }
  • ClockHolder 인터페이스를 만들고 프로덕션 환경과 테스트 환경에서 필요한 구현체를 생성하는 설계를 갖자.
    • 테스트 코드가 쉽게 깨지지 않는다.
 
 

📎 출처