[Java Spring] - Test
Test
단위 테스트
- 테스트 가능한 가장 작은 소프트웨어를 실행하여 예상대로 동작하는지 확인하는 테스트
- 개발자 관점
- 일반적으로 클래스 또는 메소드 수준으로 정해짐
- 되도록 단위의 크기를 작게 설정해, 간단하고 디버깅하기 쉽게 작성해야 한다.
Java Spring에서는 JUnit을 통해 단위 테스트를 수행할 수 있다.
@DataJpaTest
,@ExtendWith(MockitoExtension.class)
,@WebMvcTest
등의 어노테이션을 활용해 수행할 수 있다.
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
@SpringJUnitConfig
@SpringBootTest
public class UserServiceTest {
@Autowired
private UserService userService;
@MockBean
private UserRepository userRepository;
@Test
public void testGetUserById() {
// 가짜 데이터 생성
User mockUser = new User();
mockUser.setId(1L);
mockUser.setName("John Doe");
// UserRepository의 findById 메서드가 호출될 때 가짜 데이터 반환하도록 설정
when(userRepository.findById(1L)).thenReturn(mockUser);
// UserService의 getUserById 메서드 호출
User user = userService.getUserById(1L);
// 결과 확인
assertEquals("John Doe", user.getName());
}
}
통합 테스트
- 단위 기능 간의 의존성을 포함하여 테스트
- 개발자 관점
- 단위 테스트에서 가짜 객체로 배제하였던 부분을 함께 테스트
- 클래스 상단에
@SpringBootTest
어노테이션을 붙여 통합 테스트를 수행할 수 있다.
인수 테스트
- 사용자 관점
- 소프트웨어를 인수하기 전에 명세대로 작동하는지 검증하는 테스트
- 시나리오 베이스 테스트
- 도구
- MockMVC : 모킹한 Spring MVC 환경을 구현해 테스트
- RestAssured : 실제 서버를 구동해 실제 환경에서 테스트
- WebTestClient
stub, mock
stub
- 더미 객체를 생성하고 실제로 동작하는것처럼 보이게 만든 가짜 객체
- 요청에 대한 응답값을 미리 만들어 전달한다.
- 최소한의 기능만을 구현한다.
mock
- 특정 동작을 수행하는지(= 메소드를 제대로 콜 하는지)에 대한 검증을 한다.
- 즉 행위검증을 추구한다는 점에서 다른 테스트 더블들과 구분된다.
SpringBoot 계층별 테스트 방법
Controller
- Spring MVC의 요청-응답 흐름을 테스트
- 주로 HTTP 요청과 관련된 동작을 테스트하며, 컨트롤러의 메소드를 직접 호출하여 응답을 검증한다.
- 일반적으로 MockMvc를 사용하여 컨트롤러 테스트를 수행한다.
@RunWith(SpringRunner.class)
@WebMvcTest(YourController.class)
public class YourControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testYourControllerMethod() throws Exception {
mockMvc.perform(get("/your-url"))
.andExpect(status().isOk())
.andExpect(content().string("Expected Response"));
}
}
Repository
- 데이터베이스와의 상호 작용을 테스트
- 데이터베이스에 대한 CRUD(Create, Read, Update, Delete) 작업을 검증
- 내장된 H2 데이터베이스 또는 외부 데이터베이스를 사용할 수 있다.
@RunWith(SpringRunner.class)
@DataJpaTest
public class YourRepositoryTest {
@Autowired
private YourRepository yourRepository;
@Test
public void testYourRepositoryMethod() {
// Your test logic using the repository
// Example:
YourEntity entity = new YourEntity();
entity.setName("Test");
YourEntity savedEntity = yourRepository.save(entity);
Optional<YourEntity> foundEntity = yourRepository.findById(savedEntity.getId());
assertTrue(foundEntity.isPresent());
assertEquals("Test", foundEntity.get().getName());
}
}
Service
- 비즈니스 로직을 테스트
- 비스 메소드의 동작과 로직을 검증
- Repository를 Mock으로 대체하여 테스트를 수행
@RunWith(MockitoJUnitRunner.class)
public class YourServiceTest {
@InjectMocks
private YourService yourService;
@Mock
private YourRepository yourRepository;
@Test
public void testYourServiceMethod() {
// Define mock behavior
YourEntity entity = new YourEntity();
entity.setName("Test");
Mockito.when(yourRepository.findById(1L)).thenReturn(Optional.of(entity));
// Your test logic using the service
// Example:
YourEntity foundEntity = yourService.getEntityById(1L);
assertNotNull(foundEntity);
assertEquals("Test", foundEntity.getName());
}
}
Domain
- Domain 로직은 JUnit 나 AssertJ 등 테스트 편의 도구 외 다른 프레임워크의 도움이 필요하지 않다.
- 비즈니스 도메인 객체의 동작 테스트
- 도메인 객체의 메소드와 로직 검증
public class YourDomainTest {
@Test
public void testYourDomainMethod() {
// Your test logic using the domain object
// Example:
YourDomainObject domainObject = new YourDomainObject();
domainObject.setValue("Test");
assertEquals("Test", domainObject.getValue());
}
}
테스트 커버리지(JACOCO)
- Jacoco 툴을 통해 테스트 커버리지를 체크할 수 있다.
- 테스트 코드가 현재 프로덕션코드의 얼마만큼 작성되었는지 퍼센테이지로 확인하도록 해주는 라이브러리
- 커버리지가 사용자가 설정한 퍼센테이지에 미치지 못하면 build자체가 되지않게 설정됨
- 의존성을 추가하여 사용할 수 있다.
테스트 레벨
- 단위 테스트 (Unit Test)
- 테스트 가능한 가장 작은 소프트웨어가 예상대로 동작하는지 확인 (Java는 주로 Junit사용)
- 통합 테스트 (Integration Test)
- 내부 모듈의 연동과 외부 모듈의 연동을 테스트함 (springboot의 경우 @SpringBootTest)
- 인수 테스트 (Acceptance Test)
- 사용자 시나리오에 맞춰 수행하는 테스트
- end to end (Java에서는 RestAssured, MockMVC 사용)
Leave a comment