기존 프로젝트에 mockito를 이용한 테스트 코드 작성
mockito를 적용 하여 테스트 함
@ExtendWith(MockitoExtension.class)
class PostServiceTest {
@Mock
PostRepository postRepository;
@InjectMocks
PostService postService;
@Test
void createPost() {
//given
PostRequestDto request = new PostRequestDto();
User user = new User();
//when
postService.createPost(request, user);
//then
verify(postRepository, times(1)).save(any(Post.class));
}
@Test
void getPosts() {
//given
Pageable pageable = Pageable.ofSize(20);
when(postRepository.findAll(pageable))
.thenReturn(Page.empty());
//when
Page<PostResponseDto> response = postService.getPosts(pageable);
//then
// assertThat(response).isEmpty(); //todo isEmpty 에러 생겨서 주석처리
verify(postRepository, times(1)).findAll(pageable);
}
@Test
@DisplayName("게시글 조회")
void getPostById() {
//given input return
PostRequestDto request = PostRequestDto.builder()
.contents("rara")
.title("roro")
.build();
Post post = new Post(request, new User());
when(postRepository.findById(anyLong()))
.thenReturn(Optional.of(post));
//when
PostResponseDto response = postService.getPostById(anyLong());
//then
assertThat(response.getContents()).isEqualTo(request.getContents());
assertThat(response.getTitle()).isEqualTo(request.getTitle());
verify(postRepository, times(1)).findById(anyLong());
}
@Test
@DisplayName("게시글 id가 없을때 예외 발생")
void getPostById_throw() {
// given
when(postRepository.findById(anyLong())).thenReturn(Optional.empty());
// when & then
assertThrows(IllegalArgumentException.class, () -> {
postService.getPostById(0L);
});
}
@Test
@DisplayName("게시글 업데이트")
void updatePost() {
//given
PostRequestDto request = PostRequestDto.builder()
.contents("roro")
.title("roro")
.build();
User user = new User("pororo", "12345678", null, null);
Post post = new Post(request, user);
when(postRepository.findById(anyLong()))
.thenReturn(Optional.of(post));
//when
postService.updatePost(anyLong(), request, user);
//then
verify(postRepository, times(1)).save(any(Post.class));
}
@Test
@DisplayName("게시글 없데이트 (다른사람이 작성하려고 할때")
void uadatePost_invaild_user() {
//given
PostRequestDto request = PostRequestDto.builder()
.contents("rororo")
.title("roro")
.build();
User user = new User("pororo","12345678",null,null);
User user1 = new User("rupi","12345678",null,null);
Post post = new Post(request,user);
//return mocking
when(postRepository.findById(anyLong()))
.thenReturn(Optional.of(post));
//when&then
assertThrows(IllegalArgumentException.class, () -> {
postService.updatePost(anyLong(), request, user1);
});
}
}
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Mock
private JwtUtil jwtUtil;
@Spy
private BCryptPasswordEncoder passwordEncoder;
@Test
@DisplayName("로그인")
void login() {
//given
//입력값
LoginRequest request = LoginRequest.builder()
.username("pororo")
.password("pororo1234")
.build();
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
//리턴값
User user = new User("pororo", passwordEncoder.encode("pororo1234"),null, null);
when(userRepository.findByUsername(any(String.class)))
.thenReturn(Optional.of(user));
//when
ResponseStatusDto response = userService.login(request,servletResponse);
//then
assertThat(response.getStatusCode()).isEqualTo(StatusEnum.LOGIN_SUCCESS.getStatusCode());
assertThat(response.getMsg()).isEqualTo(StatusEnum.LOGIN_SUCCESS.getMsg());
assertThat(servletResponse.getHeaderValue("Authorization").toString()).isNotEmpty(); //리턴이 있는 결과값 검증
//verify는 목객체를 인자로 받아, 해당 Mock 객체의 원하는 상호작용이 있었는가 검증
verify(userRepository,times(1)).saveAndFlush(any(User.class)); //주요한 기능 함수 행위 검증할때 (마지막에 있는 로직으로 로직이 잘 돌아갔는지 확인하기위함)
}
JUnit5:
Hamcrest: JUnit의 테스트 작성을 보다 문맥적으로 자연스럽고 우아하게 할 수 있도록 도와주는 Matcher 라이브러리입니다. JUnit5부터는 Hamcrest 관련 라이브러리가 포함되어 있지 않습니다.
Gradle에 Hamcrest, Mockito 라이브러리 Dependency 추가
Intellij IDEA 최신버전에서 Gradle을 이용하여 프로젝트를 구성하면 기본적으로 JUnit5 의존성을 가집니다. JUnit5부터는 Hamcrest 관련 라이브러리가 분리되었으므로 이를 Gradle 의존성에 추가해야 하며, JUnit5에서 Mockito를 함께 사용하기 위한 의존성도 함께 작성해주어야 합니다. 또한, 예제에서는 개발 편의를 위해 Lombok을 함께 사용합니다. 생성한 프로젝트의 build.gradle을 다음과 같이 수정하고, ‘Gradle Reload’ 작업을 수행하도록 합니다.** 다만, Spring Boot (2.2+) 프로젝트를 구성한 경우에는 ‘org.springframework.boot:spring-boot-starter-test’ 라이브러리에 이미 JUnit5, Hamcrest 및 Mockito가 모두 포함되어 있으므로 이 작업이 필요 없습니다.
이를 토대로 위의 코드를 쉽게 분석할 수 있습니다. UserServiceTest는 Mockito를 사용(@ExtendWith)하고, UserRepository를 실제 객체가 아닌 Mock 객체로 바꾸어 주입(@Mock)합니다. 따라서 테스트 런타임 시 UserService의 멤버 변수로 선언된 UserRepository에 Mock 객체가 주입(InjectMocks)됩니다.
-> 테스트하지 않음 why? 리턴값도 없고, 행위지정이 없기 때문에 실행 한척 만 함