반응형
이번 포스트에서는 저번에 이어 mock을 사용한 테스트 설명을 추가적으로 이어간다.
1. Mockito.mock 사용방법 > mock으로 모의객체 생성
- Mockito.mock은 Mockito 라이브러리에서 제공하는 기능 중 하나로, 모의 객체(Mock Object)를 생성하는 데 사용된다.
- 모의 객체는 실제 객체의 동작을 흉내 내는 가짜 객체로, 테스트 시에 실제 객체를 대체하여 테스트를 수행할 수 있도록 도와준다.
- Mockito.mock 메서드를 사용하면 인터페이스, 추상 클래스 또는 클래스의 인스턴스를 가짜 객체로 만들 수 있다.
- 가짜 객체는 실제 객체의 메서드를 호출할 수 있으며, Mockito를 사용하여 원하는 동작을 정의할 수 있다. 가짜 객체는 실제 객체와 동일한 인터페이스를 가지므로 테스트 코드에서 실제 객체를 사용하는 것과 동일한 방식으로 사용할 수 있다.
1-1. 예를 들어, 다음과 같이 사용할 수 있다.
List<String> mockedList = Mockito.mock(List.class);
// 모의 객체의 동작 정의
Mockito.when(mockedList.size()).thenReturn(10);
Mockito.when(mockedList.get(0)).thenReturn("Mocked Value");
// 모의 객체 사용
System.out.println(mockedList.size()); // 출력: 10
System.out.println(mockedList.get(0)); // 출력: Mocked Value
- 위의 코드에서 mockedList는 List 인터페이스의 모의 객체이다. when 메서드를 사용하여 size 메서드가 호출될 때 10을 반환하도록, get(0) 메서드가 호출될 때 "Mocked Value"를 반환하도록 정의했다. 그 후에는 모의 객체를 사용하여 size 메서드와 get(0) 메서드를 호출하여 원하는 결과를 얻을 수 있다.
- 이와 같이 Mockito.mock을 사용하면 테스트 시에 실제 객체를 대체하고, 원하는 동작을 가진 가짜 객체를 생성하여 테스트를 수행할 수 있다.
1-2. 또다른 예시이다.
public class PostServiceTest {
@Test
void testPostCreationSuccess() {
String title = "title";
String body = "body";
String userName = "userName";
// 모의 객체 생성 및 정의
UserEntity mockUserEntity = Mockito.mock(UserEntity.class);
UserEntityRepository mockUserEntityRepository = Mockito.mock(UserEntityRepository.class);
// UserRepository 모의 객체의 동작 정의
Mockito.when(mockUserEntityRepository.findByUserName(userName)).thenReturn(Optional.of(mockUserEntity));
// PostService에 UserRepository 모의 객체를 주입하여 테스트
PostService postService = new PostService(mockUserEntityRepository);
// 예외가 발생하지 않아야 함
Assertions.assertDoesNotThrow(() -> postService.create(title, body, userName));
}
}
- 위의 예시 코드는 PostService의 create 메서드를 테스트하는 코드이다.
- UserEntity의 모의 객체 mockUserEntity와 UserEntityRepository의 모의 객체 mockUserEntityRepository를 생성하고, mockUserEntityRepository의 findByUserName 메서드가 호출되면 Optional.of(mockUserEntity)를 반환하도록 정의한다.
- 그 후, PostService에 mockUserEntityRepository를 주입하여 테스트를 수행한다. postService.create(title, body, userName) 코드에서 예외가 발생하지 않아야 성공으로 간주한다.
2. Optional로 Mock 객체를 감싼 이유
Optional로 객체를 감싸는 것은 필수는 아니다. 테스트 코드에서 Optional로 모의 객체를 감싸는 것은 선택 사항이다.
2-1. Optional.of를 사용하는 이유는 다음과 같다.
- 일관성 유지
- 테스트 코드에서 실제 코드와 유사한 방식으로 동작하기 위해 Optional.of를 사용할 수 있다.
- 실제 코드에서 findByUserName 메서드가 Optional을 반환한다면, 테스트 코드에서도 동일한 방식을 사용하여 일관성을 유지할 수 있다.
- 테스트 코드에서 실제 코드와 유사한 방식으로 동작하기 위해 Optional.of를 사용할 수 있다.
- 검증 및 테스트의 명확성
- Optional.of를 사용하면 반환된 값이 null인지 아닌지를 명확하게 표현할 수 있다.
- 예를 들어, 테스트 코드에서 Optional을 반환하는 메서드를 검증할 때, Optional.of를 사용하면 반환값이 null인 경우와 Optional.empty()인 경우를 명확하게 구분할 수 있다.
- Optional.of를 사용하면 반환된 값이 null인지 아닌지를 명확하게 표현할 수 있다.
- 예외 방지
- Optional.of를 사용하면 null을 반환하는 메서드를 호출했을 때 발생할 수 있는 NullPointerException을 방지할 수 있다.
- Optional을 사용하면 값이 존재하지 않는 경우에도 예외를 던지지 않고 처리할 수 있다.
- Optional.of를 사용하면 null을 반환하는 메서드를 호출했을 때 발생할 수 있는 NullPointerException을 방지할 수 있다.
하지만, 테스트 코드에서 Optional.of로 감싸는 것은 필수적인 것은 아니다.
테스트 코드에서 직접 null 값을 반환해도 문제가 없다면 Optional 변환을 사용하지 않아도 된다.
Optional 변환을 사용할지에 대한 여부는 개발자의 판단에 따라 결정할 수 있다.
2023.08.09 - [Spring 테스트코드] - Spring(스프링) - 테스트 코드의 기초(3)
2023.08.09 - [Spring 테스트코드] - Spring(스프링) - 테스트 코드의 기초(5) [CRUD 테스트]
반응형
'Spring > 테스트 코드' 카테고리의 다른 글
[스프링, 스프링 부트] Spring test - service 테스트에서 만난 오류 (0) | 2023.08.16 |
---|---|
[스프링, 스프링 부트] Spring test - Mock에 대한 이해 (0) | 2023.08.09 |
[스프링, 스프링부트] Spring test - 테스트 코드의 기초(5) [CRUD 테스트] (0) | 2023.08.09 |
[스프링, 스프링 부트] Spring test - 테스트 코드의 기초(3) [Mockito.when() 메서드] (0) | 2023.08.09 |
[스프링, 스프링 부트] Spring test - 테스트 코드의 기초(2) [MockMvc, MockBean] (0) | 2023.08.09 |