Junit 초기 설정
//@DataJpaTest //Tranjectional あるため、テスト後ロールバックします。
@ExtendWith(MockitoExtension.class)
public class BookServiceTest {
@InjectMocks
private BookService bookService;
@Mock
private BookRepository bookRepository;
@Mock
private MailSender mailSender;
// @Autowired
// private BookRepository bookRepository;
// 気になる… サービスだけテストしたいけど、レポジトリもテストになる Mockito使用
@ExtendWith(MockitoExtension.class) : Mockito와 Junit5를 같이 사용하기 위해서 사용한다.
@InjectMock은 DI를 @Mock이나 @Spy로 생성된 mock 객체를 자동으로 주입해주는 어노테이션입니다.
@Mock으로 만든 mock 객체는 가짜 객체이며 그 안에 메소드 호출해서 사용하려면 반드시 스터빙(stubbing)을 해야합니다.
해석해보자면, BookService를 Test하기 위해 Mokito를 이용한다. (가짜 객체를 생성)
@InjectMocks를 이용해서 실제 BookService를 DI해주고,,
@Mock을 이용해서 가짜로 된 DB인 BookRepository와 메일을 보내기 위한 클래스 MailSender를 가짜 객체로 만든다.
이것은 추후에 stub이란 스터빙을 해줘야 하는데 이것은 아래에서 다루겠다.
1.Book 등록 테스트
@Test
public void bookSaveTest() {
//given
BookSaveReqDto dto = new BookSaveReqDto();
dto.setTitle("junit-seo");
dto.setAuthor("meta-seo");
//stub(行動定義)
when(bookRepository.save(any())).thenReturn(dto.toEntity());
when(mailSender.send()).thenReturn(true);
//when
BookRespDto bookRespDto = bookService.bookSave(dto);
//then
// assertEquals(dto.getTitle(), bookRespDto.getTitle());
// assertEquals(dto.getAuthor(), bookRespDto.getAuthor());
assertThat(bookRespDto.getTitle()).isEqualTo(dto.getTitle());
assertThat(bookRespDto.getAuthor()).isEqualTo(dto.getAuthor());
}
이제는 실제로 Service쪽을 테스트를 해보겠다.
추가로 stub이란 항목이 생겼다.
stub이란,, 테스트 용도로 하드 코딩한 값을 반환하는 구현체를 의미한다...
databse와 connect 하거나 web service를 call 할 수 있는지에대해 test하고 싶은 것이 아닙니다. 따라서, 이와 같은 부분들은 하드코딩으로 대체하고, 우리가 test 하고자하는 business logic에 집중하고자 Stub을 사용한다.
해석해보자면,
given// BookSaveReqDto dto를 만들고, dto에 값을 임의로 넣어준다.
stub// 에서는 반환을 위해 when을 사용. thenReturn의 리턴값으로 방금 임의로 넣어준 dto를 toEntity로 객체로 만들어 준다. 그 후 bookRepository의 save메서드를 이용해서 값을 저장.
when// 에서는 BookRespDto 에 방금 dto로 세이브한 값을 넣어준다.
Request -> BookSaveReqDto -> toEntity()를 이용 Book객체로 builder한다.-> BookRespDto에 저장->Response
마지막으로 assertThat // bookRespDto에 저장한 값과 SaveReqDto에 들어온 값을 비교해준다.
2. Book리스트 테스트
@Test
public void bookListTest() {
//given(パラメータから入るデータ)
//stub(仮説)
List<Book> books = new ArrayList<>();
books.add(new Book(1L, "junit-seo", "meta-seo"));
books.add(new Book(2L, "spring-seo", "coding-seo"));
when(bookRepository.findAll()).thenReturn(books);
//when(実行)
List<BookRespDto> bookRespDtoList = bookService.bookList();
//print
bookRespDtoList.stream().forEach((dto)-> {
System.out.println(dto.getId());
System.out.println(dto.getTitle());
System.out.println(dto.getAuthor());
System.out.println("2.-------------------------------------------------------------------------");
});
//then(検証)
assertThat(bookRespDtoList.get(0).getTitle()).isEqualTo("junit-seo");
assertThat(bookRespDtoList.get(0).getAuthor()).isEqualTo("meta-seo");
assertThat(bookRespDtoList.get(1).getTitle()).isEqualTo("spring-seo");
assertThat(bookRespDtoList.get(1).getAuthor()).isEqualTo("coding-seo");
}
List는 검색이기에 given을 따로 받을 필요 없다.
stub에서 List<Book> books = new ArrayList<>(); 를 사용하는 이유를 알아보자...
ArrayList는 구현체가 아닌 List인터페이스로 작성된다.
ArrayList를 업캐스팅 하는 이유는 유연성을 위한 것이다.
ArrayList<>()의 빠른 탐색과 검색을 이용하면서 List의 장점인 유연성을 이용한 것이다.
stub// List<Book> books = new Array<>();를 이용해서 리스트에 books를 담는다.
books.add는 List형태의 삽입 메서드 이며 new해서 객체를 넣은 이유는
리스트로써 안에 객체들이 들어있는 경우를 생각하여, 리스트 안에 각 객체를 추가한 것이다.
when 으로 bookRepository.findAll() 로 지금까지 등록한 books를 가져온다.
when// List로 된BookRespDto를 만들어 bookService의 bookList메서드를 실행시켜 방금stub에서 설정한 값을 가져온다.
print// 값을 눈으로 확인하기 위해 쓴 코드 이다. List이기 때문에 stream의 foreach을 이용해서 sysout을 구현했다.
해석 해보자.. bookRespDtoList는 방금 만든 List이다. 그것을 stream으로 하고 foreach로 dto로 변수를 만들어 안에 있는 값들을 프린트 한다.
then// assertThat을 이용해서 List의 get(0)번째와 isEqualTo("값") 을 비교해준다.
북 수정과 검색은 다음 게시물에서 진행하도록 하겠다.
'개발 > Junit' 카테고리의 다른 글
⑦Junit Controller 초기설정 및 책 등록, 책 리스트 보기 (0) | 2022.10.22 |
---|---|
⑥Service Junit 테스트 - 4 검색 수정 junit테스트 (0) | 2022.10.20 |
④Junit Service 테스트 -2 Service book List, Search (0) | 2022.10.19 |
③Junit Service 테스트 -1 Service book등록 (0) | 2022.10.18 |
②Junit 에 대해서 공부하자.! bookList, booksearch, bookdelete (0) | 2022.10.18 |
댓글