✏️ 0617
Spring 심화 강의
개인과제 제출 및 해설 영상
통합 테스트란 무엇인가
아무튼 한꺼번에 다같이 테스트 하나보지 뭐..(낡고지침
통합 테스트란?
두 개 이상의 단위가 함께 잘 작동하는지 확인하는 테스트
통합 테스트와 단위 테스트를 비교해보자
단위 테스트
소스 코드의 개별 단위, 모듈이나 메서드 등을 대상으로 정상 작동하는지 검증
- 장점
- 코드를 작은 단위로 나눠서 테스트 하기 때문에 빠르게 실행되어 확인 가능
- 오류가 발생하면 해당 오류를 쉽고 빠르게 찾아 수정 가능
- 단점
- 단일 모듈, 함수에 대한 테스트만 수행하므로 전체 시스템의 동작을 보장할 수 없다
- 모의 객체를 사용해 의존성을 처리해야 할 때가 많아 실제 환경과 다를 수 있다
통합 테스트
여러 단위, 소프트웨어의 모듈 간에 올바르게 통신하는지, 잘 전달하는지 등 검증
- 장점
- 모듈 간의 상호작용을 실제 환경과 유사하게 테스트할 수 있다
- 시스템의 전체적인 작동을 확인할 수 있어서 품질 보장 가능
- 단점
- 전체 시스템을 테스트하므로 실행이 느리고 비용이 많이 든다
- 오류 발생 시, 무엇이 문제인지 찾기 어렵다
단위 테스트와 통합 테스트는 서로 다른 측면을 검증한다
단위 테스트는 개별 단위의 동작을 검증하는데 집중되어 있고,
통합 테스트는 여러 단위가 함께 잘 작동하는지 검증하는데 집중되어 있다
이러한 차이점을 이해해서 적절한 상황에 사용함으로써 테스트 코드를 잘 작성할 수 있도록 하자...
Spring Boot 를 이용한 통합 테스트
통합 테스트를 사용하면 Repository 부분 까지도 한번에 같이 사용하면서 테스트할 수 있다
이게 무슨 소리냐면
일반적으로 단위 테스트할 때는 빠르게 실행되도록 설계 되어 Spring Context 를 불러오지 않는다
이 경우, Spring IoC / DI 기능을 사용할 수 없고 DB 연결이나 트랜잭션 같은 기능도 사용할 수 없다
대신 가짜 객체 Mock Object 를 통해서 테스트를 작성할 수 있다
하지만
@SpringBootTest 는 Spring Boot 애플리케이션을 테스트할 때 사용하는 어노테이션으로,
Spring Context 를 불러와서 통합 테스트를 수행할 수 있게 도와준다
그러면 IoC / DI 기능은 물론 Repository 도 사용가능 하며 DB CRUD 가 가능해진다
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ProductServiceIntegrationTest {
@Test
@Order(1)
void test1() {
// 생략
}
}
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
Spring Boot 애플리케이션 컨텍스트를 불러오고, 내장된 서버의 포트를 랜덤으로 설정한다
이를 통해 테스트가 실제 서버 환경에서 실행되는 것처럼 동작하게 한다
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
JUnit 5에서 테스트 인스턴스의 생명 주기를 클래스로 설정한다
이를 통해 테스트 클래스의 각 메서드가 동일한 테스트 인스턴스를 공유하게 된다
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
테스트 메서드의 실행 순서를 @Order 으로 지정할 수 있다
이를 통해 테스트 메서드의 실행 순서를 제어할 수 있다
강의 과제 내용
Test 는 Java 의 Main Method 를 사용해서 도는 게 아니라
Test Platform 이 따로 있어서 독립적인 Test 환경이 따로 존재한다
그래서 기본적으로 Test 메서드는 독립적으로 따로 실행이 된다
같이 수행되면 서로 영향을 받으니 제대로된 단위 테스트를 위해서
서로의 영향이 받지 않게 하려고 기본적으로 각각의 메서드 하나씩 다른 환경에서 돌아간다
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ProductServiceIntegrationTest {
User user;
ProductResponseDto createdProduct = null;
int updatedMyPrice = -1;
@Test
void test1() { }
}
그래서 위의 코드 처럼 필드를 선언해 두어도 같이 사용할 수 없는데
이때 @TestInstance(TestInstance.Lifecycle.PER_CLASS) 를 추가해서
테스트 인스턴스의 생성 단위를 클래스로 변경할 수 있다
이를 통해 위의 필드를 공유하고 하나처럼 돌도록 만들 수 있다
.. 여태 @BeforeEach 선언하고 setUp() 메서드 사용해서 필드 선언했는데
이런 게 있었네 ㅎㅎ..
그래서 찾아봤다 차이점
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
테스트 인스턴스의 생명주기를 클래스 단위로 설정하고 각 테스트 메서드가 동일한 인스턴스를 공유하는 방식
이를 통해 필드를 선언해두고 테스트 메서드 간에 공유할 수 있다
@BeforeEach setUp()
각 테스트 메서드가 독립적인 인스턴스를 사용하는 방식
각 테스트 메서드가 실행되기 전에 공통 설정을 수행할 수 있다
각 테스트 메서드가 동일한 인스턴스를 공유하는 방식
- 장점
- 필드 공유
클래스 수준에서 상태를 공유할 수 있어 상태가 변하지 않는 테스트에서 효율적 - 설정 비용 감소
설정이 복잡하고 비용이 많이 드는 경우, 인스턴스를 한번만 생성하고 재사용이 가능해 성능에 유리
- 필드 공유
- 단점
- 상태 공유의 위험
테스트 간의 상태가 공유되므로, 하나의 테스트가 다른 테스트에 영향을 줄 수 있다
이로 인해 테스트의 독립성이 깨질 수 있다 - 코드 복잡성 증가
테스트 상태 관리가 복잡해질 수 있으며, 분필요한 상태 공유로 인한 버그가 발생할 수 있다
- 상태 공유의 위험
각 테스트 메서드가 독립적인 인스턴스를 사용하는 방식
- 장점
- 독립성
각 테스트 메서드가 독립적으로 수행되므로, 테스트 간의 상태 공유 문제를 피할 수 있다
테스트의 신뢰성 상승 - 단순함
테스트 상태 관리가 단순해지며 코드가 더 직관적
- 독립성
- 단점
- 설정 비용
각 테스트 메서드 실행 전에 설정을 반복해야 하므로, 설정 비용이 큰 경우 성능에 영향이 미칠 수 있다
- 설정 비용
❇️ 결론
테스트는 신뢰성과 독립성을 유지하는 것이 가장 중요
일반적으론 독립적인 인스턴스를 사용하는 방식을 사용하는 것이 더 권장된다고 한다
테스트의 독립성을 보장하며 코드가 더 단순하고 직관적이기 때문
설정 비용이 매우 크거나, 테스트 간에 상태를 공유하고 순서대로 진행되어야 하는 경우에인스턴스를 공유하는 방식을 사용하면 된다고 한다
이 내용이 틀렸고 맞지 않다면
관련 블로그나 자료를 댓글 남겨주시면 감사하겠습니당
'개발 일지 > TIL' 카테고리의 다른 글
[ #45 ] TIL (0) | 2024.06.19 |
---|---|
[ #44 ] TIL (0) | 2024.06.18 |
[ #42 ] TIL (0) | 2024.06.14 |
[ #41 ] TIL (0) | 2024.06.13 |
[ #40 ] TIL (0) | 2024.06.12 |