테스트 코드를 작성하면서 처음에 이해가 잘 되지 않았던 개념에 대해 정리
Mock
Mock : 가짜 객체
Mocking은 소프트웨어 개발과 테스트에서 매우 중요한 개념으로, 실제 객체를 대체하여 테스트할 수 있는 가짜 객체(mock objects)를 만드는 기술이다. 주로 단위 테스트(unit testing)에서 사용되며, 다음과 같은 상황에서 유용하다.
- 외부 종속성 격리: 데이터베이스, 네트워크, 파일 시스템 등 외부 종속성을 격리하여 테스트를 수행할 수 있다
- 테스트 속도 향상: 외부 시스템에 의존하지 않으므로 테스트 실행 속도가 빨라진다
- 테스트 신뢰성 향상: 외부 시스템의 상태나 응답 시간에 영향을 받지 않으므로 더 신뢰할 수 있는 테스트를 작성할 수 있다
- 특정 시나리오 테스트: 예외 상황이나 특정 경로를 쉽게 테스트할 수 있다
Spring에서 mocking을 구현하기 위해서 주로 Mockito를 사용한다.
1. 의존성 추가
testImplementation 'org.mockito:mockito-core:4.0.0'
2. Mock객체 선언
@Mock ,@MockBean을 사용해 Mock객체를 선언
@Mock : 스프링 컨텍스트와 무관하게 Mockito에서 동작
@InjectMock : 생성된 Mock객체를 주입. Mockito의 어노테이션이다.
@MockBean: 스프링 테스트에서지원. 스프링 컨텍스트에 Mock 객체를 주입할 수 있다. @SpringbootTest 어노테이션을 사용하면 ApplicationContext을 모두 로드하는데, @MockBean 어노테이션이 선언된 Mock객체를 실제 Bean대신 ApplicationContext에 주입한다.
given when then
Given-When-Then은 Behavior Driven Development(BDD)와 테스트 주도 개발(TDD)에서 사용되는 패턴으로, 테스트를 작성할 때 코드의 구조를 명확히 하고 이해하기 쉽게 만든다. 이 패턴은 테스트 시나리오를 세 부분으로 나누어 각 단계의 목적과 역할을 명확히 한다.
- Given: 테스트의 초기 상태를 설정. 여기서는 테스트 대상 객체를 초기화하고 필요한 mock 객체를 설정하며, 각종 초기 데이터를 준비
- When: 테스트할 동작을 실행. 보통 단일 메서드 호출이나 특정 동작을 수행
- Then: 기대하는 결과를 검증. 이 단계에서는 assert 문이나 verify 메서드를 사용하여 실제 결과가 기대하는 결과와 일치하는지 확인
예시)
게시글을 작성하는 NewsfeedService의 테스트
@Test
@DisplayName("게시글 작성 성공")
@Order(1)
void postContent_success() {
// given
String token = jwtUtil.createAccessToken(USERNAME);
String content = "newsfeed content";
NewsfeedRequestDto newsfeedRequestDto = new NewsfeedRequestDto();
newsfeedRequestDto.setContent(content);
String encodedPassword = passwordEncoder.encode(PASSWORD);
User user = new User(USERNAME, encodedPassword, USERNAME, EMAIL, UserStatus.ACTIVE);
given(userRepository.findByUsername(USERNAME)).willReturn(Optional.of(user));
// when
ResponseEntity<NewsfeedResponseDto> response = newsfeedService.postContent(token,
newsfeedRequestDto);
// then
assertEquals(Objects.requireNonNull(response.getBody()).getContent(), content);
}
Stubbing
User user = new User(USERNAME, encodedPassword, USERNAME, EMAIL, UserStatus.ACTIVE);
given(userRepository.findByUsername(USERNAME)).willReturn(Optional.of(user));
given단계에서 필요한 데이터를 준비하고, given()메서드를 이용해 UserRepository.findByUsername(USERNAME))의 값을 미리 stubbing 해 두었다.
userRepository는 mock객체이기 때문에 실제 데이터베이스와 상호작용을 하지 않기 때문에 Mockito를 사용하여 특정 메서드 호출에 대해 원하는 값을 설정해 주어야 한다. 이것을 "stubbing" 이라고 한다.
mock 객체는 실제 객체와 동일한 인터페이스나 클래스를 구현하지만, 실제 메서드 호출이 아닌 우리가 설정한 동작을 수행한다. 따라서 mock 객체는 주어진 시나리오에서 필요한 동작을 테스트하기 위한 도구로 사용된다.
'TIL' 카테고리의 다른 글
2024.06.18.화 테스트 어노테이션 정리 (1) | 2024.06.19 |
---|---|
2024.06.17.월 일대다 단방향 매핑 (0) | 2024.06.18 |
2024.06.13.목 자바 스프링 테스트 (0) | 2024.06.14 |
2024.06.12.수 Spring AOP (1) | 2024.06.13 |
2024.06.11.화 도메인등록하고 EC2연결해보기 (0) | 2024.06.12 |