Server/JUnit, Spock

JUnit5 - 단위 테스트에서 프로퍼티 불러오기

JaeHoney 2022. 6. 2. 23:37

테스트 코드를 작성하다보면 Property에서 값을 가져오는 일이 많이 생긴다. 그런데 @Value("${property-path}")를 사용해도 프로퍼티 값이 불러와지지 않는다.

 

해당 포스팅에서는 단위 테스트에서 프로퍼티를 가져오는 방법에 대해 다룬다.

1. @TestPropertySource

@TestPropertySource를 사용하면 해당 파일의 프로퍼티를 읽을 수 있다.

@TestPropertySource(locations = "classpath:application.yml"))
@SpringBootTest(classes = UserService.class)
public class UserServiceTest {

    private UserService userservice;

    @Value("${property-path}")
    private String property;
    
}

다만 해당 방법에는 문제가 있는데 해당 테스트 클래스는 UserServiceImpl 클래스의 단위 테스트를 수행하는 클래스이다. 그런데 테스트 클래스에는 프로퍼티가 잘 삽입되지만, 실제 프로덕션 클래스의 필드에는 프로퍼티 값이 삽입되지 않는다. 해당 애노테이션이 포함된 테스트 클래스에만 적용되기 때문이다.

 

물론 @SpringBootTest를 사용해서 스프링부트 애플리케이션의 모든 빈을 다 등록하면 프로퍼티가 제대로 필드에 삽입된다. 하지만 이는 단위테스트에 어울리지 않다.

2. @EnableConfigurationProperties

@EnabledConfigurationProperties를 사용하면 테스트에서도 property를 사용할수 있고, 실제 프로덕션 클래스에서도 프로퍼티를 삽입할 수 있다.

@EnableConfigurationProperties
@SpringBootTest(classes = UserService.class)
public class UserServiceTest {

    private UserService userservice;

    @Value("${property-path}")
    private String property;
    
}

이렇게 하면 대부분 프로퍼티를 잘 사용할 수 있을 것이다.

 

아래의 경우에는 정상적으로 적용되지 않을 수 있다.

@EnableConfigurationProperties
@SpringBootTest(classes = UserService.class)
public class UserServiceTest {

    private UserService userservice;

    @Value("${test.user.name}")
    private String testName;
    
    private User testUser = new User(testName);
    
}

필드 레벨에서 testUser를 초기화하면서 프로퍼티 값이 testName에 삽입되기 전에 참조하는데 이때 testName은 null을 가지게 된다.

 

이런 경우에는 아래의 방법을 고려하면 된다.

  1. 다른 Configuration 클래스에서 Bean으로 해당 프로퍼티 값을 등록하고 의존성을 주입받아서 사용한다.
  2. 다른 클래스에서 필드에 프로퍼티 값을 삽입한 후 해당 클래스를 상속받아서 필드에 접근한다.
  3. Method 레벨에서 testUser 초기화를 진행한다.
    • @BeforeAll 메서드는 static이기 때문에 해당 필드를 초기화할 수 없다.
      • @TestInstance(Lifecycle.PER_CLASS)를 사용하면 non-static으로도 가능하다.
      • 테스트 메서드간 인스턴스를 공유하므로 개인적으로 선호하지 않는다.
    • @BeforeEach 에서 초기화할 수 있다.
    • TestMethod 내부에서 초기화도 가능하다.

Reference