[JUnit]테스트 코드 공부하기(5)

gamja·2023년 1월 18일
0
post-thumbnail

💻BookService 본코드 작성

	// 2. 책목록보기
    public List<BookRespDto> 책목록보기(){
        return bookRepository.findAll().stream()
                    .map((new BookRespDto() :: toDto)
                    .collect(Collectors.toList)); 
                    // map으로 해주는 이유 : map으로 하면 stream으로 들어온 object를 복제하여 다른 타입으로 변경이 가능하다. 
    }

🤚Stream 잠시 공부하고 지나가기

stream().map() 동작

stream에 book들이 object 타입으로 들어오면 들어온 object들을 다른 타입으로 변경을 하여 리턴을 할 수 있다. 그리고 변경된 object들은 복제된 것들이고, 기존의 object들은 건드리지 않는다.

🔍stream은 물길과 같다. 물길에는 물고기들이 차례대로 헤엄치고 있는데, 그걸 filter로 걸러서 map이라는 통에 담을 수 있다. 그러면 다시 filter로 걸러진 물고기만 존재하는 stream이 만들어진다.


🧩Mokito - 가짜 환경 만들기

package site.metacoding.junitproject.service;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;

import site.metacoding.junitproject.domain.BookRepository;
import site.metacoding.junitproject.util.MailSender;
import site.metacoding.junitproject.web.dto.BookRespDto;
import site.metacoding.junitproject.web.dto.BookSaveReqDto;

@ExtendWith(MockitoExtension.class)
public class BookServiceTest {

    @InjectMocks
    private BookService bookService;    // 얘는 autowired로 메모리에 못 올린다. 

    @Mock
    private MailSender mailSender;      

    @Mock
    private BookRepository bookRepository;

    @Test
    public void 책등록하기_테스트(){
        // given (파라미터로 들어올 데이터)
        BookSaveReqDto dto = new BookSaveReqDto();
        dto.setTitle("junit강의");
        dto.setAuthor("이보통");
        
        // stub (가설)
        when(bookRepository.save(any())).thenReturn(dto.toEntity());   // 행동정의  - return 값을 정하는 것(thenReturn값으로 리턴값을 대체해준다.)
        when(mailSender.send()).thenReturn(true);                                  // 가설이라고 생각하면 됨

        // when (실행)
        BookRespDto bookRespDto = bookService.책등록하기(dto);
        
        // then (검증)
  	    assertThat(dto.getTitle()).isEqualTo(bookRespDto.getTitle());   // assertThat : 실제값, isEqualTo : 내가 기대하는 값
        assertThat(dto.getAuthor()).isEqualTo(bookRespDto.getAuthor());
        
    }
    
     @Test
    public void 책목록보기_테스트(){
        // given (파라미터로 들어올 데이터)

        // stub (가설)
        List<Book> books = new ArrayList<>();
        books.add(new Book(1L, "junit강의", "메타코딩"));
        books.add(new Book(2L, "spring강의", "겟인데어"));

        when(bookRepository.findAll()).thenReturn(books);   // books가 return되도록 설정

        // when (실행)
        List<BookRespDto> dtos = bookService.책목록보기();

        // then (검증)
        assertThat(dtos.get(0).getTitle()).isEqualTo("junit강의");
    }
}

  • @ExtendWith(MockitoExtension.class) : 가짜 환경을 만들어준다.
  • @Mock : 가짜 환경에 가짜 Repository, 가짜 MailSender가 올라간다.
  • @InjectMocks : 클래스를 new 시켜주고, 가짜 환경에 올라가 있는 Mock클래스들이 BookService에 주입된다.

🔧 Repository에 어떤값을 넣든 가짜 클래스이기 때문에 제대로 된 값이 나올 수가 없다. 따라서 when().thenReturn()을 통해서 내가 원하는 값이 return 되도록 설정을 해준다. 즉, 행동정의 를 해주는 것이다.

assertEquals보다는 assertThat이 더 좋은 이유

  • 테스트에서 필요한 거의 모든 메소드를 제공
  • 메소드 체이닝을 지원해서 더 짧고 간결하게 코드 작성 가능
  • 가독성 높음

🚀책목록보기_테스트 실행 결과

실패원인 : "junit강의"를 기대했는데 "spring강의"를 return하였다.
본코드에 문제가 있는 것으로 예상됨.

🔨본코드 수정

 // 2. 책목록보기
    public List<BookRespDto> 책목록보기(){
        List<BookRespDto> dtos =  bookRepository.findAll().stream()
                    .map((bookPS) -> new BookRespDto().toDto(bookPS))
                    .collect(Collectors.toList()); // map으로 해주는 이유 : map으로 하면 stream으로 들어온 object를 복제하여 다른 타입으로 변경이 가능하다. 

        return dtos;	
    }

위와 같이 수정해주고 테스트 코드를 다시 실행해주면 테스트 성공!

assertJ 참고 블로그
https://velog.io/@sdb016/AssertJ-%EA%B8%B0%EB%B3%B8-%EC%82%AC%EC%9A%A9%EB%B2%95

profile
눈도 1mm씩 쌓인다.

0개의 댓글

관련 채용 정보