@Autowired 생성자 주입 방식이 테스트가 용이한 이유

백엔드&인프라 추종자·2025년 2월 26일

스프링 공부

목록 보기
15/35

🚀 생성자 주입 방식이 테스트가 용이한 이유


1. final 필드를 사용할 수 있어 불변성을 보장

  • 생성자 주입 방식에서는 final 키워드를 사용할 수 있음
  • 객체가 생성된 이후에는 의존성이 변경될 수 없으므로, 안정성이 높아짐
@Service
public class UserService {
    private final UserRepository userRepository;

    @Autowired
    public UserService(UserRepository userRepository) {  // 생성자를 통한 주입
        this.userRepository = userRepository;
    }
}
  • final 필드로 선언된 userRepository한 번 할당된 이후 변경 불가능
  • 의존성이 변경되지 않아 예측 가능한 테스트 작성이 가능

2. 의존성 주입 없이도 테스트 가능 (Spring Container 불필요)

  • Setter 주입, 필드 주입 방식@Autowired가 필요하여, Spring Context를 실행해야 테스트 가능
  • 생성자 주입 방식new 키워드를 이용해 직접 객체를 생성하여 테스트 가능

(1) 생성자 주입 방식 - 독립적인 단위 테스트 가능

@Test
void testUserService() {
    UserRepository mockRepository = mock(UserRepository.class);
    UserService userService = new UserService(mockRepository);  // 직접 주입 가능

    // 테스트 수행...
}

Spring 없이도 객체 생성 및 주입이 가능하여 빠른 단위 테스트 가능

(2) 필드 주입 방식 - Spring Context가 필요함

@SpringBootTest
class UserServiceTest {

    @Autowired  // Spring이 주입해야 함
    private UserService userService;

    @Test
    void testUserService() {
        // userService가 주입되려면 Spring Context가 실행되어야 함
    }
}

단점: @Autowired를 사용하면, 테스트 실행 시 Spring Context가 필요하여 속도가 느려지고, 독립적인 단위 테스트가 어려움


3. 의존성 누락 방지 (컴파일 타임 체크 가능)

  • 생성자 주입 방식에서는 필수 의존성이 없으면 컴파일 에러 발생
  • 필드 주입, Setter 주입 방식은 런타임에서만 오류가 발생 가능
// 생성자 주입 방식
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {  // 필수 의존성 체크 가능
        this.userRepository = userRepository;
    }
}

final 필드이므로 userRepository주입되지 않으면 컴파일 에러 발생
⚠ 반면, 필드 주입이나 Setter 주입 방식에서는 NullPointerException이 런타임에서 발생할 가능성이 있음


4. 테스트 시 Setter 주입보다 더 안전

  • Setter 주입 방식은 필요할 때만 주입할 수 있어 테스트 시 의존성이 변경될 위험이 있음
// Setter 주입 방식 (테스트 시 setUserRepository를 통해 변경 가능)
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
@Test
void testUserService() {
    UserService userService = new UserService();
    userService.setUserRepository(mockRepository1);  // 한 번 주입

    // 다른 테스트에서
    userService.setUserRepository(mockRepository2);  // 다른 객체로 변경 가능 (테스트 신뢰도↓)
}

문제점:

  • 테스트 환경에서 의존성이 변경될 가능성이 있어 일관된 테스트가 어려움

생성자 주입 방식은 Setter 없이 한 번만 주입되므로, 테스트 시 예측 가능한 결과를 유지


🎯 정리

주입 방식장점단점
생성자 주입 (Constructor Injection) ✅final 필드 사용 가능 → 불변성 유지, 컴파일 타임 체크 가능, Spring 없이 단위 테스트 가능의존성이 많아지면 생성자가 길어질 수 있음
필드 주입 (Field Injection)코드가 짧고 간결함@Autowired 필요 → Spring Context 실행 필수, 테스트 어려움
Setter 주입 (Setter Injection)선택적 의존성 주입 가능테스트 시 의존성이 변경될 위험 존재

결론

  • 테스트의 독립성과 안정성을 유지하려면 "생성자 주입 방식"이 가장 적합
  • Spring 없이 객체를 생성할 수 있어 "빠른 단위 테스트 가능"
  • 의존성이 변경되지 않도록 보장하여 "테스트 결과의 신뢰도 증가" 🚀
profile
AI 답변 글을 주로 올립니다.

0개의 댓글