테스트코드
1️⃣ 통합 테스트
테스트 환경설정
통합 테스트는 애플리케이션의 전체 컨텍스트를 로드하여 실제 운영 환경과 유사한 조건에서 테스트를 수행합니다.
이 방식은 애플리케이션의 모든 부분이 서로 어떻게 상호작용하는지를 파악하는 것이 목적입니다.
의존성 관리
@MockBean을 사용하여 실제 컴포넌트와의 상호작용을 모의합니다.
이를 통해 실제 환경에서 발생할 수 있는 다양한 상황들을 시뮬레이션할 수 있습니다.
💡 @MockBean
스프링부트테스트에서 제공하는 어노테이션입니다.
mock객체를 스프링 컨텍스트에 등록해서, @SpringBootTest를 통해 @Autowired로 의존성이 주입됩니다.
(@Autowired 동작할 때 이 mock객체로 사용)
테스트 실행방식
MockMvc를 이용해 HTTP 요청과 응답을 모의하며, 이를 통해 컨트롤러의 전체적인 행동을 검증합니다.
이 접근 방식은 웹 애플리케이션의 통신 흐름을 실제와 유사하게 테스트할 수 있게 해줍니다.
목적/효율성
애플리케이션의 전반적인 동작과 컴포넌트 간의 상호작용을 포괄적으로 검증하는 것에 목적을 둡니다.
애플리케이션의 안정성을 확보하는 데 중요한 역할을 합니다.
2️⃣ 단위 테스트
테스트 환경설정
단위 테스트는 격리된 환경에서 진행되며, 필요한 부분만 모의 객체를 이용해 테스트를 진행하여 각 기능이나 메서드가 독립적으로 올바르게 동작하는지 빠르고 효율적으로 검증하는 것이 목적입니다.
의존성 관리
@Mock과 @InjectMocks 어노테이션을 활용해 필요한 의존성만을 주입하고, 외부 요소와의 상호작용을 최소화합니다.
테스트의 범위를 좁혀서 특정 기능 또는 메서드에만 집중할 수 있게 해줍니다.
💡 @Mock
클래스/인터페이스의 mock(가짜)객체를 생성합니다.
메서드의 반환값을 조작하거나, 호출여부를 확인할 수 있습니다.
@ExtendWith(MockitoExtension.class) 메서드로 활성화 후 사용 가능합니다. (JUnit5)
@InjectMocks
@Mock을 통해 주입된 mock객체들을 @InjectMocks로 선언된 객체에 주입해줍니다.
테스트 실행방식
단위 테스트에서는 컨트롤러의 메서드를 직접 호출하여 각 메서드가 기대한 대로 동작하는지 집중적으로 검증합니다.
목적/효율성
각 기능이나 메서드의 정확성과 신뢰성을 빠르고 효율적으로 검증하는 것에 초점을 맞춥니다.
개발 과정 중에 발생할 수 있는 문제를 조기에 발견하고 수정하는 데 도움을 줍니다.
3️⃣ 가짜객체 사용하기
@MockBean
기존에 사용되던 Bean의 껍데기만 가져오고, 내부 구현은 모두 사용자에게 위임한 형태입니다.
@MockBean
private MemberRepository memberRepository;
@Test
public void test_1() {
final Long ID = 1L;
given(memberRepository.findById(ID))
.willReturn(Optional.empty());
}
Mock 객체를 사용하면, 테스트 수행 시 스프링 Bean이 아닌 Mock Bean을 주입합니다.
MockBean의 사용으로, “기존 Bean의 메소드가 어떤 값을 리턴해야 한다”는 개발자가 테스트하고자하는 임의의 내용을 조작할 수 있게 해줍니다.
Bean이 어떤 행동을 하면 어떤 결과를 반환한다는 가정을 선언하는 given절에서 사용합니다.
@SpyBean
Bean을 SpyBean으로 래핑한 형태로, 사용법은 @MockBean과 동일합니다.
*주의: 인터페이스 Bean(JpaRepository, HttpSession 등)에서는 작동하지 않습니다. 즉, Repository에서는 @SpyBean 대신 @MockBean을 사용해야합니다
🧐 @MockBean vs @SpyBean
@MockBean : given에서 선언한 코드 외에는 전부 사용 불가능
@SpyBean : given에서 선언한 코드 외에는 모두 실제 객체를 사용
4️⃣ given, when, then 패턴
준비, 실행, 검증의 단계로 테스트코드를 작성합니다.
given
테스트를 위한 준비 과정으로, 테스트에 사용되는 변수나 입력값들을 정의하거나 Mock 객체를 정의합니다.
// given
final String id = 1L;
final Member = new Member(id);
when(repositroy.findOne(id))
.thenReturn(member);
Mockito 메소드의 when 구문을 사용했지만, 결국 검증하기 위한 어떤 테스트에 필요한 과정 중 하나이기 때문에 given에 해당합니다.
when
실제로 검증할 테스트를 실행합니다.
// when
String savedId = service.register(id);
테스트를 작성하는 목적에 해당하는 것으로, 짧지만 가장 중요한 구문입니다.
then
예상한 값과 실제 실행한 값을 비교하여 테스트를 검증하는 단계입니다.
// then
assertThat(id).isEqualTo(savedId);