controller
package com.cos.demo.web;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cos.demo.domain.Book;
import com.cos.demo.service.BookService;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@RestController
public class BookController {
private final BookService bookService;
@PostMapping("/book")
public ResponseEntity<?> save(@RequestBody Book book){
return new ResponseEntity<>(bookService.saveBook(book), HttpStatus.CREATED);
}
@GetMapping("/book")
public ResponseEntity<?> findAll(){
return new ResponseEntity<>(bookService.getAllBook(), HttpStatus.OK);
}
@GetMapping("/book/{id}")
public ResponseEntity<?> findById(@PathVariable Long id){
return new ResponseEntity<>(bookService.getBook(id), HttpStatus.OK);
}
@PutMapping("/book/{id}")
public ResponseEntity<?> update(@PathVariable Long id, @RequestBody Book book){
return new ResponseEntity<>(bookService.getBook(id), HttpStatus.OK);
}
@DeleteMapping("/book/{id}")
public ResponseEntity<?> deleteById(@PathVariable Long id){
return new ResponseEntity<>(bookService.deletBook(id), HttpStatus.OK);
}
}
1. 통합테스트 - BookControllerItegreTest
package com.cos.demo.web;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.transaction.annotation.Transactional;
import com.cos.demo.domain.Book;
import com.cos.demo.domain.BookRepository;
import com.cos.demo.service.BookService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
/**
* 통합테스트 (모든 Bean 들을 똑같이 IOC 에 올리고 테스트하는 것)
* WebEnvironment.MOCK=실제 톰켓을 올리는것이 아니라, 다른 톰켓으로 테스트
* WebEnvironment.RANDOM_PORT = 실제 톰켓으로 테스트
*
* @AutoConfigureMockMvc MockMvc 를 IOC 에 등록해줌.
* @Transactional 은 각각의 테스트함수가 종료될 때만다 트랜잭션을 rollback 해주는 어노테이션
*/
@Slf4j
@Transactional
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
public class BookControllerItegreTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private BookRepository bookRepository;
@Autowired
private EntityManager entityManager;
// @BeforeEach
// public void init(){
// List<Book> books =new ArrayList<Book>();
// books.add(new Book(null,"스프링부트 따라하기","코스"));
// books.add(new Book(null,"리엑트 따라하기","코스"));
// books.add(new Book(null,"JUnit 따라하기","코스"));
// bookRepository.saveAll(books);
// entityManager.createNativeQuery("ALTER TABLE book ALTER COLUMN id RESTART WITH 1").executeUpdate();
// //entityManager.createNativeQuery("ALTER TABLE book AUTO_INCREMENT=1").executeUpdate();
// }
//
// @AfterEach
// public void end(){
// bookRepository.deleteAll();
// }
@Test
public void save_테스트() throws Exception {
log.info("save_테스트() 시작 ==========================");
//given (테스트를 하기 위한 준비)
Book book=new Book(null, "스프링 따라하기", "코스");
String content=new ObjectMapper().writeValueAsString(book);
log.info(content);
//when(테스트 실행)
ResultActions resultActions =mockMvc.perform(post("/book").contentType(
MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON));
//then(검증) //https://jsonpath.com/
resultActions
.andExpect(status().isCreated())
.andExpect(jsonPath("$.title").value("스프링 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void findAll_테스트() throws Exception{
//given
List<Book> books=new ArrayList<>();
books.add(new Book(1L,"스프링부트 따라하기", "코스"));
books.add(new Book(2L,"리엑트 따라하기", "코스"));
bookRepository.saveAll(books);
//when
ResultActions resultActions=mockMvc.perform(get("/book")
.accept(MediaType.APPLICATION_JSON));
//공식문서 : https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing
//https://jsonpath.com/
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$", Matchers.hasSize(2)))
.andExpect(jsonPath("$.[0].title").value("스프링부트 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void findById_테스트() throws Exception{
List<Book> books =new ArrayList<Book>();
books.add(new Book(null,"스프링부트 따라하기","코스"));
books.add(new Book(null,"리엑트 따라하기","코스"));
books.add(new Book(null,"JUnit 따라하기","코스"));
bookRepository.saveAll(books);
Long id=1L;
ResultActions resultActions=mockMvc.perform(get("/book/{id}", id)
.accept(MediaType.APPLICATION_JSON));
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.title").value("스프링부트 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void update_테스트() throws Exception{
Long id=1L;
List<Book> books =new ArrayList<Book>();
books.add(new Book(null,"스프링부트 따라하기","코스"));
books.add(new Book(null,"리엑트 따라하기","코스"));
books.add(new Book(null,"JUnit 따라하기","코스"));
bookRepository.saveAll(books);
Book book=new Book(id, "C++ 따라하기","코스");
String content=new ObjectMapper().writeValueAsString(book);
//영속성 객체 가져오기
Book entitiy=bookRepository.findById(id).orElseThrow(()->new IllegalArgumentException("ID 를 찾을 수 없습니다."));
entitiy.setTitle(book.getTitle());
//when
ResultActions resultActions=mockMvc.perform(
put("/book/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
.accept(MediaType.APPLICATION_JSON));
//공식문서 : https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing
//https://jsonpath.com/
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.title").value("C++ 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void delete_테스트() throws Exception{
Long id=1L;
Book book=new Book(id, "C++ 따라하기","코스");
bookRepository.save(book);
//삭제처리시 예상값
//when(bookService.deletBook(id)).thenReturn("ok");
//when
ResultActions resultActions=mockMvc.perform(delete("/book/{id}", id)
.accept(MediaType.TEXT_PLAIN));
//then
resultActions
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print());
MvcResult requestResult=resultActions.andReturn();
String result=requestResult.getResponse().getContentAsString();
log.info("1.resultActions ==>{}", resultActions);
log.info("2.result ==>{}", result);
assertEquals("ok", result);
}
}
2. 단위 테스트 -BookControllerUnitTest
package com.cos.demo.web;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import java.util.ArrayList;
import java.util.List;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import com.cos.demo.domain.Book;
import com.cos.demo.service.BookService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
//단위테스트(Controller 관련 로직만 띄우기) Filter, ControllerAdvice
@Slf4j
//@Transactional
@WebMvcTest
public class BookControllerUnitTest {
@Autowired
private MockMvc mockMvc;
@MockBean //IoC 환경에 bean 등록됨.
private BookService bookService;
//BDDMockito 패턴 given, when, then
@Test
public void save_테스트() throws Exception {
log.info("save_테스트() 시작 ==========================");
//given (테스트를 하기 위한 준비)
Book book=new Book(null, "스프링 따라하기", "코스");
String content=new ObjectMapper().writeValueAsString(book);
log.info(content);
//결과값을 미리 설정
when(bookService.saveBook(book)).thenReturn(new Book(1L,"스프링 따라하기", "코스"));
//when(테스트 실행)
ResultActions resultActions =mockMvc.perform(post("/book").contentType(
MediaType.APPLICATION_JSON).content(content).accept(MediaType.APPLICATION_JSON));
//then(검증) //https://jsonpath.com/
resultActions
.andExpect(status().isCreated())
.andExpect(jsonPath("$.title").value("스프링 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void findAll_테스트() throws Exception{
//given
List<Book> books=new ArrayList<>();
books.add(new Book(1L,"스프링부트 따라하기", "코스"));
books.add(new Book(2L,"리엑트 따라하기", "코스"));
//결과값을 미리 설정
when(bookService.getAllBook()).thenReturn(books);
//when
ResultActions resultActions=mockMvc.perform(get("/book")
.accept(MediaType.APPLICATION_JSON));
//공식문서 : https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing
//https://jsonpath.com/
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$", Matchers.hasSize(2)))
.andExpect(jsonPath("$.[0].title").value("스프링부트 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void findById_테스트() throws Exception{
Long id=1L;
when(bookService.getBook(id)).thenReturn(new Book(1L, "자바 공부하기", "쌀"));
ResultActions resultActions=mockMvc.perform(get("/book/{id}", id)
.accept(MediaType.APPLICATION_JSON));
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.title").value("자바 공부하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void update_테스트() throws Exception{
Long id=1L;
Book book=new Book(id, "C++ 따라하기","코스");
String content=new ObjectMapper().writeValueAsString(book);
//결과값을 미리 설정
when(bookService.updateBook(id,book)).thenReturn(new Book(id,"C++ 따라하기","코스"));
//when
ResultActions resultActions=mockMvc.perform(
put("/book/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.content(content)
.accept(MediaType.APPLICATION_JSON));
//공식문서 : https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.testing
//https://jsonpath.com/
//then
resultActions
.andExpect(status().isOk())
.andExpect(jsonPath("$.title").value("C++ 따라하기"))
.andDo(MockMvcResultHandlers.print());
}
@Test
public void delete_테스트() throws Exception{
Long id=1L;
Book book=new Book(id, "C++ 따라하기","코스");
bookService.saveBook(book);
//삭제처리시 예상값
when(bookService.deletBook(id)).thenReturn("ok");
//when
ResultActions resultActions=mockMvc.perform(delete("/book/{id}", id)
.accept(MediaType.TEXT_PLAIN));
//then
resultActions
.andExpect(status().isOk())
.andDo(MockMvcResultHandlers.print());
MvcResult requestResult=resultActions.andReturn();
String result=requestResult.getResponse().getContentAsString();
log.info("1.resultActions ==>{}", resultActions);
log.info("2.result ==>{}", result);
assertEquals("ok", result);
}
}
3. 서비스 - BookServiceUnitTest
package com.cos.demo.service;
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 com.cos.demo.domain.BookRepository;
//단위테스트(Controller, Filter, ControllerAdvice)
//BookRepository => 가짜 객체로 만들 수 있음.
@ExtendWith(MockitoExtension.class)
public class BookServiceUnitTest {
@InjectMocks //BookService 객체가 만들어 질때 BookServiceUnitTest 파일에 @Mock 로 등록된 모든 애들을 주입받는다.
private BookService bookService;
@Mock
private BookRepository bookRepository;
@Test
public void save_테스트(){
}
}
4. Repository - BookRepositoryUnitTest
package com.cos.demo.domain;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.transaction.annotation.Transactional;
//단위테스트(Controller, Filter, ControllerAdvice
@Transactional
@AutoConfigureTestDatabase(replace = Replace.ANY) //Replace.ANY 가짜 디비로 테스트, Replace.None 실제 DB 로 테스트
@DataJpaTest() //Repository 들을 다 IOC 등록해둠.
public class BookRepositoryUnitTest {
@Autowired
private BookRepository bookRepository;
@Test
public void save_테스트(){
Book book=new Book(null,"책제목1","책저자1");
Book bookEntity=bookRepository.save(book);
assertEquals("책제목1", bookEntity.getTitle());
}
}
1.
2.
3.
4.

















댓글 ( 4)
댓글 남기기