@TestConfiguration을 통해서 테스트를 위한 빈 등록하기

byeol·2023년 8월 9일
0

@TestConfiguration의 사용은 이 리뷰에서 시작된다.

바우처 미션은 JPA를 사용하지 않고 JDBC로 구현되기 때문에 key를 직접 생성해줘야 했다.

나는 랜덤값으로 생성되도록 선택했는데 ( 추후에는 UUID 중에서 정렬이 가능한 UUID를 선택했지만 이 내용에 관해서는 추후에 다루어볼 예정이다.) 서브멘토님께서 이 부분에 대해서 계속 무언가 힌트를 주셨었다.

따라서 아래의 물음에서 시작된다.

테스트할 때 어떤 수를 직접 넣고 싶다면 어떻게 할 것인가? 🤔

정해진 숫자를 넣어서 만들 수 있는지를 테스트하고 싶다면 어떻게 할 것인가?

내가 쉽게 답을 찾지 못해서 직접적인 방향성을 제시해 주셨다.

바로 interface로 만들어서

하나는 운영할 때, 하나는 테스트할 때 사용할 수 있도록 구현하는 것이다.

인터페이스

import java.time.LocalDateTime;

public interface Generator {
    String makeKey();

    LocalDateTime makeDate();

}

구현체

  • 하나는 실제 비즈니스에서 사용하고

    @Component
    public class GeneratorImp implements Generator {
    
       @Override
       public String makeKey() {
           UUID generateId = Generators.timeBasedGenerator().generate();
           String[] idArr = generateId.toString().split("-");
    
           return  idArr[2]+"-"+idArr[1]+"-"+idArr[0]+"-"+idArr[3]+"-"+idArr[4] ;
       }
    
       @Override
       public LocalDateTime makeDate() {
           return LocalDateTime.now();
       }
    
    }
  • 다른 하나는 테스트할 때 사용한다. 아래와 같이 직접 입력된 값으로

    public class TestGeneratorImp implements Generator {
    
       @Override
       public String makeKey() {
           return "22";
       }
    
       @Override
       public LocalDateTime makeDate() {
           String str = "2023-07-29 13:47:13.248";
           DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd  HH:mm:ss.SSS");
           return LocalDateTime.parse(str, formatter);
       }
    }

근데 위 코드를 보고 아래와 같은 의문이 생길 수 있다.

TestGeneratorImp를 빈으로 등록하지 않았는데 테스트할 때
어떻게 인터페이스를 통해서 가져올 것이며 등록했다 하더라도
같은 종류의 빈이 2개 등록되어 있는데 어떻게 테스트를 위한 빈을 우선적으로 가져올 것인가? 🤔

Test만을 위한 빈을 등록하고 이 빈을 다른 같은 종류의 빈보다 우선적으로 가져올 수 있는 방법은 없을까? 🤔

어떤 사람은@Primary를 이용하여 하면되지 라고 말할 수 있다.

그러면 이 과정이 필요하다.

  • TestGeneratorImp를 빈으로 등록

  • 테스트할 때 이 빈을 사용하기 위해서 TestGeneratorImp에 들억가서 @Primary를 넣어준다


위 방법의 단점이 무엇일까
  • 실제 코드에서 필요하지 않은 테스트 빈이 등록되어 있다.

  • 테스트 할 때마다 가서 @Primary를 넣어줘야 한다. 그러나 만약에 내가 이걸 잊어버리고 안 지운다면?

따라서 이러한 단점을 해결해주는 것이 @TestConfiguration이었다.

@TestConfiguration을 이용하여 테스트를 위한 빈을 등록해보자 ✨

  1. Config 파일을 test 폴더 아래에 만들어준다.

  2. Config 파일에서 @TestConfiguration을 통해서 내가 테스트 시 사용하고자 하는 빈을 만들어 등록한다.

    그러면 테스트할 때 Generator로 등록된 두 개의 빈(TestConfig, GeneratorImp) 중에서 내가 @TestConfiguration으로 등록한 빈을 우선적으로 선택한다.

    import com.prgrms.common.util.Generator;
    import com.prgrms.common.util.TestGeneratorImp;
    import org.springframework.boot.test.context.TestConfiguration;
    import org.springframework.context.annotation.Bean;
    
    @TestConfiguration
    public class TestConfig {
    
       @Bean
       Generator generator() {
           return new TestGeneratorImp();
       }
    
    }
  3. 그리고 마지막으로 @Import를 통해서 테스트할 때 직접적으로 빈을 가져와야 한다.

    @Transactional
    @SpringBootTest
    @Import({TestConfig.class})
    class VoucherServiceTest {
  4. 마지막으로 정말 내가 주입하고자 하는 빈이 주입되었는지 디버그로 확인해보자.

    @Transactional
    @SpringBootTest
    @Import({TestConfig.class})
    class VoucherServiceTest {
    
       final static String FIXED_ID = "22";
       final static String PERCENT_ID = "40";
       final static double DISCOUNT_AMOUNT = 20;
    
       @Autowired
       VoucherService voucherService;
    
       @Autowired
       VoucherRepository voucherRepository;
    
       @Test
       @DisplayName("만들고자 하는 바우처를 createVoucher()로 만들었을 때 기대값과 같은 바우처를 반환한다.")
       void createVoucher_RepositoryInsertVoucher_Equals() {
           //given
           VoucherType voucherType = VoucherType.FIXED_AMOUNT_VOUCHER;
           Discount discount = new FixedDiscount(DISCOUNT_AMOUNT);
           VoucherServiceCreateRequest serviceCreateRequest = new VoucherServiceCreateRequest(voucherType,DISCOUNT_AMOUNT);
    
           //when
           VoucherServiceResponse result = voucherService.createVoucher(serviceCreateRequest);
    
           //then
           assertThat(result.voucherId())
                   .isNotNull()
                   .isEqualTo("22");
       }
    

    디버깅 모드를 통해서 보면 voucherService와 관계를 맺은 빈을 보면
    TestGeneratorImp이 주입된 것을 확인할 수 있다.

profile
꾸준하게 Ready, Set, Go!

0개의 댓글