- 소스 확인
@WebMvcTest(ProductController.class)
//@AutoConfigureWebMvc // 이 어노테이션을 통해 MockMvc를 Builder 없이 주입받을 수 있음
public class ProductControllerTest {
@Autowired
private MockMvc mockMvc;
// ProductController에서 잡고 있는 Bean 객체에 대해 Mock 형태의 객체를 생성해줌
@MockBean
ProductServiceImpl productService;
// http://localhost:8080/api/v1/product-api/product/{productId}
@Test
@DisplayName("Product 데이터 가져오기 테스트")
void getProductTest() throws Exception {
// given : Mock 객체가 특정 상황에서 해야하는 행위를 정의하는 메소드
given(productService.getProduct("12315")).willReturn(
new ProductDto("15871", "pen", 5000, 2000));
String productId = "12315";
// andExpect : 기대하는 값이 나왔는지 체크해볼 수 있는 메소드
mockMvc.perform(
get("/api/v1/product-api/product/" + productId))
.andExpect(status().isOk())
.andExpect(jsonPath("$.productId").exists()) // json path의 depth가 깊어지면 .을 추가하여 탐색할 수 있음 (ex : $.productId.productIdName)
.andExpect(jsonPath("$.productName").exists())
.andExpect(jsonPath("$.productPrice").exists())
.andExpect(jsonPath("$.productStock").exists())
.andDo(print());
// verify : 해당 객체의 메소드가 실행되었는지 체크해줌
verify(productService).getProduct("12315");
}
@Test
@DisplayName("Product 데이터 생성 테스트")
void createProductTest() throws Exception {
//Mock 객체에서 특정 메소드가 실행되는 경우 실제 Return을 줄 수 없기 떄문에 아래와 같이 가정 사항을 만들어줌
given(productService.saveProduct("15871", "pen", 5000, 2000))
.willReturn(new ProductDto("15871", "pen", 5000, 2000));
ProductDto productDto = ProductDto.builder().productId("15871").productName("pen").productPrice(5000).productStock(2000).build();
/*Gson gson = new Gson();
String content = gson.toJson(productDto);*/
// Gson대신 dto 객체를 json형태 변경 작업을 대체 가능
String content = new ObjectMapper().writeValueAsString(productDto);
mockMvc.perform(
post("/api/v1/product-api/product")
.content(content)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isAccepted())
.andExpect(jsonPath("$.productId").exists())
.andExpect(jsonPath("$.productName").exists())
.andExpect(jsonPath("$.productPrice").exists())
.andExpect(jsonPath("$.productStock").exists())
.andDo(print());
verify(productService).saveProduct("15871", "pen", 5000, 2000);
}
}
1) getProductTest 확인
// http://localhost:8080/api/v1/product-api/product/{productId}
@Test
@DisplayName("Product 데이터 가져오기 테스트")
void getProductTest() throws Exception {
// given : Mock 객체가 특정 상황에서 해야하는 행위를 정의하는 메소드
given(productService.getProduct("12315")).willReturn(
new ProductDto("15871", "pen", 5000, 2000));
String productId = "12315";
// andExpect : 기대하는 값이 나왔는지 체크해볼 수 있는 메소드
mockMvc.perform(
get("/api/v1/product-api/product/" + productId))
.andExpect(status().isOk())
.andExpect(jsonPath("$.productId").exists()) // json path의 depth가 깊어지면 .을 추가하여 탐색할 수 있음 (ex : $.productId.productIdName)
.andExpect(jsonPath("$.productName").exists())
.andExpect(jsonPath("$.productPrice").exists())
.andExpect(jsonPath("$.productStock").exists())
.andDo(print());
// verify : 해당 객체의 메소드가 실행되었는지 체크해줌
verify(productService).getProduct("12315");
}
[2023-07-31 17:32:38.976] [INFO ] [main] c.s.s.i.c.ProductController [ProductController] perform '1690792358976' of seypak API.
[2023-07-31 17:32:38.980] [INFO ] [main] c.s.s.i.c.ProductController [ProductController] Response :: productId ='15871', productName ='pen', productPrice ='5000', productStock ='2000', Response Time = '4'ms
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/v1/product-api/product/12315
Parameters = {}
Headers = []
Body = null
Session Attrs = {}
Handler:
Type = com.seypak.study.intellij.controller.ProductController
Method = co m.seypak.study.intellij.controller.ProductController#getProduct(String)
비동기로 처리했는지
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
뷰를 다루고있지 않기때문에 null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"productId":"15871","productName":"pen","productPrice":5000,"productStock":2000}
Forwarded URL = null
Redirected URL = null
Cookies = []
2) createProductTest 확인
@Test
@DisplayName("Product 데이터 생성 테스트")
void createProductTest() throws Exception {
//Mock 객체에서 특정 메소드가 실행되는 경우 실제 Return을 줄 수 없기 떄문에 아래와 같이 가정 사항을 만들어줌
given(productService.saveProduct("15871", "pen", 5000, 2000))
.willReturn(new ProductDto("15871", "pen", 5000, 2000));
ProductDto productDto = ProductDto.builder().productId("15871").productName("pen").productPrice(5000).productStock(2000).build();
/*Gson gson = new Gson();
String content = gson.toJson(productDto);*/
// Gson대신 dto 객체를 json형태 변경 작업을 대체 가능
String content = new ObjectMapper().writeValueAsString(productDto);
mockMvc.perform(
post("/api/v1/product-api/product")
.content(content)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isAccepted())
.andExpect(jsonPath("$.productId").exists())
.andExpect(jsonPath("$.productName").exists())
.andExpect(jsonPath("$.productPrice").exists())
.andExpect(jsonPath("$.productStock").exists())
.andDo(print());
verify(productService).saveProduct("15871", "pen", 5000, 2000);
}
[2023-07-31 18:07:23.069] [INFO ] [main] c.s.s.i.c.ProductController [createProduct] Response >> productId ='15871', productName ='pen', productPrice ='5000', productStock ='2000'
MockHttpServletRequest:
HTTP Method = POST
Request URI = /api/v1/product-api/product
Parameters = {}
Headers = [Content-Type:"application/json;charset=UTF-8", Content-Length:"81"]
Body = {"productId":"15871","productName":"pen","productPrice":5000,"productStock":2000}
Session Attrs = {}
Handler:
Type = com.seypak.study.intellij.controller.ProductController
Method = co m.seypak.study.intellij.controller.ProductController#createProduct(ProductDto)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 202
Error message = null
Headers = [Content-Type:"application/json"]
Content type = application/json
Body = {"productId":"15871","productName":"pen","productPrice":5000,"productStock":2000}
Forwarded URL = null
Redirected URL = null
Cookies = []
Process finished with exit code 0
예외발생테스트1) .productId를 1111로 변경했는데 Null Exception이 발생해 원인파악중.
ProductDto productDto = ProductDto.builder().productId("1111").productName("pen").productPrice(5000).productStock(2000).build();
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
at co m.seypak.study.intellij.controller.ProductControllerTest.createProductTest(ProductControllerTest.java:73)
Caused by: java.lang.NullPointerException
at co m.seypak.study.intellij.controller.ProductController.createProduct(ProductController.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:197)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:141)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:894)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1063)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
... 85 more
Class transformation time: 0.0878916s for 7125 classes or 1.2335663157894737E-5s per class
Process finished with exit code -1
'JAVA > SpringBoot' 카테고리의 다른 글
[SpringBoot] Jacoco 테스트 커버리지 설명 (0) | 2023.08.07 |
---|---|
[SpringBoot] JUnit 테스트코드 - Service (0) | 2023.08.07 |
[SpringBoot] JUnit 설명 (0) | 2023.07.28 |
[SpringBoot] Validation (유효성 검사/데이터 검증) (0) | 2023.07.27 |
[SpringBoot] Logback 설정 (0) | 2023.07.27 |