문제 상황
@SpringBootTest(classes = {***.class, ***.class})
@ExtendWith(MockitoExtension.class)
class ExampleTest {
@Mock
private Repository repository;
@Mock
private Service service;
@Mock
private ServerPort serverPort;
@Autowired
private MessageSource messageSource;
@Autowired
private ExampleTask task;
}
1. @Autowired로 테스트 클래스를 주입받지 못하는 이유
@Autowired는 스프링이 관리하는 스프링 빈만 자동으로 주입할 수 있습니다. 하지만, ExampleTask는 테스트 코드에서 따로 생성되어 있지 않아, 스프링 컨텍스트에서 관리되지 않아 사용할 수 없습니다.
(@SpringBootTest 어노테이션을 사용하면 가능하지만, 단위테스트에 어긋남)
ExampleTask에 @Autowired를 등록하였을 때 스프링 컨텍스트 내에 주입할 수 있는 빈이 존재하지 않는다는 아래와 같은 에러 메시지가 발생하였습니다.
No qualifying bean of type 'net.mgrv.scheduler.task.space_reservation.service.SpaceReserveStartingTask' available”
2. MessageSource에 @ExtendWith(SpringExtension.class)로 못 받는 이유
@ExtendWith(SpringExtension.class)을 통해 스프링 컨텍스트 환경을 구축되는 것은 @Component로 선언된 빈만 등록이 됩니다. 해당 빈은 Config 클래스에 빈으로 등록되어 있어, 인식하지 못합니다.
그래서 저는 테스트 코드에 따로 MessageSource 컴포넌트를 등록한 후 @SpringBootTest 어노테이션을 통해 특정 빈을 명시하여 사용하였습니다.
해결 방법
스프링 컨텍스트가 설정해 주는 부분과 mocktio 객체가 설정되는 부분에서 빈 주입이 꼬이는 문제가 있어 @BeforeEach 어노테이션을 통해 테스트가 실행되기 전에 생성자 의존성 주입으로 의존성을 설정하였습니다.
테스트 코드가 아닌 실제 코드에 있는 빈을 주입받아 테스트하기보다는 mock 객체를 통해 테스트하는 클래스가 정상적으로 동작하는지 확인하고 싶어 생성자를 통한 의존성 주입을 통해 테스트를 진행하였습니다.
다른 의존하는 클래스(Service - MessageSource)에 관련된 빈들이 있어 이를 최소한으로 @SpringBootTest를 통해 스프링 컨텍스트에 등록해 주어 빈을 주입하는 형식으로 테스트 클래스와 의존하는 클래스에 의존성 문제를 해결하였습니다.
@SpringBootTest(classes = {***.class, ***.class})
@ExtendWith(MockitoExtension.class)
class ExampleTest {
@Mock
private Repository repository;
@Mock
private Service service;
@Mock
private ServerPort serverPort;
@Autowired
private MessageSource messageSource;
@Autowired
private ExampleTask task;
@BeforeEach
void setUp() {
spaceReserveService = new SpaceReserveService(messageSource);
task = new SpaceReserveStartingTask(spaceReserveRepository, spaceReserveService,
messageServerPort);
}
}
느낀점
테스트 코드를 작성할 때 모든 빈을 주입받아 사용하는 것은 테스트 코드 실행에 큰 비용을 잡아먹으므로, 필요한 빈만 주입해야 한다.
여러 의존성이 있는 클래스에 대해 단위 테스트를 작성해 보면서 빈의 의존성을 어떻게 처리하는지 배우는 시간이었습니다.
1. 테스트하려는 클래스가 의존하는 클래스는 무엇인지,
2. 내가 테스트하려고 하는 핵심적인 부분은 무엇인지,
3. Mocking을 처리할 테스트는 무엇인지,
등에 대해 고민해 보며 서비스 단위테스트에서 원하는 관심사를 올바르게 테스트하는 방법을 익혔습니다.
'트러블슈팅' 카테고리의 다른 글
[트러블슈팅] Spring DateTimeFormatter 생성 비용 최적화 (0) | 2024.11.07 |
---|---|
H2 Database TINYINT(1) 설정 오류 해결: CommandAcceptanceException 및 JdbcSQLSyntaxErrorException 해결 방법 (1) | 2024.10.05 |
[Mac] iTerms2 개발 환경 세팅하기 (2) | 2024.09.08 |
[트러블슈팅] Spring Cache Redis - List 역직렬화MismatchedInputException 해결 (0) | 2024.08.17 |
[트러블슈팅] Jib 빌드 이미지 실행 이슈 해결 - Error: Unable to access jarfile app.jar (0) | 2024.08.09 |