출처 : https://youtu.be/SFVWo0Z5Ppo
예를들어
1이라는 기능을 고치기 위해서 기능 수정을 함. 메소드가 1과 2기능을 사용하고 있을때 코드수정함으로 2가 동작할 수 있지 않기 때문에. 테스트를 돌려보고 정상적으로 통과하면 side-effect가 없다고 판단할 수 있음)TestEngine API의 구현체로 JUnit 5를 구현하고 있음.
테스트의 실제 구현체는 별도 모듈 역할을 수행하는데, 그 모듈 중 하나가 Jupiter-Engine임
이 모듈은 Jupiter-API를 사용하여 작성한 테스트 코드를 발견하고 실행하는 역할을 수행
개발자가 테스트 코드를 작성할 때 사용됨
Platform을 Jupiter가 구현하고있다고 생각하면 됨.
Test를 실행하기 위한 뼈대
Test를 발견하고 테스트 계획을 생성하는 TestEngine 인터페이스를 가지고 있음
TestEngine을 통해 Test를 발견하고, 수행 및 결과를 보고함
그리고 각종 IDE 연동을 보조하는 역할을 수행(콘솔 출력 등)
(Platform=TestEngine API + Console Launcher + JUnit 4 Based Runner 등)
TestEngine API 구현체로 JUnit 3,4 를 구현하고 있음.
기존 JUnit 3,4 버전으로 작성된 테스트 코드를 실행할 때 사용됨.
Vintage-Engine 모듈을 포함하고 있음.
실습
package com.example.testproject.test;
import org.junit.jupiter.api.*;
public class TestLifeCycle {
@BeforeAll
static void beforeAll(){
System.out.println("## BeforeAll Annotation 호출 ##");
System.out.println();
}
@AfterAll
static void afterAll(){
System.out.println("## afterAll Annotation 호출 ##");
System.out.println();
}
@BeforeEach
void beforeEach(){
System.out.println("## beforeEach Annotation 호출 ##");
System.out.println();
}
@AfterEach
void afterEach(){
System.out.println("## afterEach Annotation 호출 ##");
System.out.println();
}
@Test
void test1(){
System.out.println("## test1 시작 ##");
System.out.println();
}
@Test
@DisplayName("Test Case 2!!!")
void test2(){
System.out.println("## test2 시작 ##");
System.out.println();
}
@Test
@Disabled // Disabled Annotation : 테스트를 실행하지 않게 설정하는 어노테이션
void test3(){
System.out.println("## test3 시작 ##");
System.out.println();
}
}
-- 결과
"C:\Program Files\Java\jdk-17.0.3.1\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\lib\idea_rt.jar=55183:C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Users\oiio6\.m2\repository\org\junit\platform\junit-platform-launcher\1.8.2\junit-platform-launcher-1.8.2.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2022.2.3\plugins\junit\lib\junit-rt.jar;E:\youtube_Springboot\TestProject\target\test-classes;E:\youtube_Springboot\TestProject\target\classes;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.7.4\spring-boot-starter-web-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter\2.7.4\spring-boot-starter-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot\2.7.4\spring-boot-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.7.4\spring-boot-autoconfigure-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.7.4\spring-boot-starter-logging-2.7.4.jar;C:\Users\oiio6\.m2\repository\ch\qos\logback\logback-classic\1.2.11\logback-classic-1.2.11.jar;C:\Users\oiio6\.m2\repository\ch\qos\logback\logback-core\1.2.11\logback-core-1.2.11.jar;C:\Users\oiio6\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;C:\Users\oiio6\.m2\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;C:\Users\oiio6\.m2\repository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;C:\Users\oiio6\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;C:\Users\oiio6\.m2\repository\org\yaml\snakeyaml\1.30\snakeyaml-1.30.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.7.4\spring-boot-starter-json-2.7.4.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.13.4\jackson-databind-2.13.4.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.13.4\jackson-core-2.13.4.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.4\jackson-datatype-jdk8-2.13.4.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.4\jackson-datatype-jsr310-2.13.4.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.4\jackson-module-parameter-names-2.13.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.7.4\spring-boot-starter-tomcat-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.65\tomcat-embed-core-9.0.65.jar;C:\Users\oiio6\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.65\tomcat-embed-websocket-9.0.65.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-web\5.3.23\spring-web-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-beans\5.3.23\spring-beans-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-webmvc\5.3.23\spring-webmvc-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-aop\5.3.23\spring-aop-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-context\5.3.23\spring-context-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-expression\5.3.23\spring-expression-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-configuration-processor\2.7.4\spring-boot-configuration-processor-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\projectlombok\lombok\1.18.24\lombok-1.18.24.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-test\2.7.4\spring-boot-starter-test-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-test\2.7.4\spring-boot-test-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\2.7.4\spring-boot-test-autoconfigure-2.7.4.jar;C:\Users\oiio6\.m2\repository\com\jayway\jsonpath\json-path\2.7.0\json-path-2.7.0.jar;C:\Users\oiio6\.m2\repository\net\minidev\json-smart\2.4.8\json-smart-2.4.8.jar;C:\Users\oiio6\.m2\repository\net\minidev\accessors-smart\2.4.8\accessors-smart-2.4.8.jar;C:\Users\oiio6\.m2\repository\org\ow2\asm\asm\9.1\asm-9.1.jar;C:\Users\oiio6\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;C:\Users\oiio6\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;C:\Users\oiio6\.m2\repository\org\assertj\assertj-core\3.22.0\assertj-core-3.22.0.jar;C:\Users\oiio6\.m2\repository\org\hamcrest\hamcrest\2.2\hamcrest-2.2.jar;C:\Users\oiio6\.m2\repository\org\junit\jupiter\junit-jupiter\5.8.2\junit-jupiter-5.8.2.jar;C:\Users\oiio6\.m2\repository\org\junit\jupiter\junit-jupiter-api\5.8.2\junit-jupiter-api-5.8.2.jar;C:\Users\oiio6\.m2\repository\org\opentest4j\opentest4j\1.2.0\opentest4j-1.2.0.jar;C:\Users\oiio6\.m2\repository\org\junit\platform\junit-platform-commons\1.8.2\junit-platform-commons-1.8.2.jar;C:\Users\oiio6\.m2\repository\org\apiguardian\apiguardian-api\1.1.2\apiguardian-api-1.1.2.jar;C:\Users\oiio6\.m2\repository\org\junit\jupiter\junit-jupiter-params\5.8.2\junit-jupiter-params-5.8.2.jar;C:\Users\oiio6\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.8.2\junit-jupiter-engine-5.8.2.jar;C:\Users\oiio6\.m2\repository\org\junit\platform\junit-platform-engine\1.8.2\junit-platform-engine-1.8.2.jar;C:\Users\oiio6\.m2\repository\org\mockito\mockito-core\4.5.1\mockito-core-4.5.1.jar;C:\Users\oiio6\.m2\repository\net\bytebuddy\byte-buddy\1.12.17\byte-buddy-1.12.17.jar;C:\Users\oiio6\.m2\repository\net\bytebuddy\byte-buddy-agent\1.12.17\byte-buddy-agent-1.12.17.jar;C:\Users\oiio6\.m2\repository\org\objenesis\objenesis\3.2\objenesis-3.2.jar;C:\Users\oiio6\.m2\repository\org\mockito\mockito-junit-jupiter\4.5.1\mockito-junit-jupiter-4.5.1.jar;C:\Users\oiio6\.m2\repository\org\skyscreamer\jsonassert\1.5.1\jsonassert-1.5.1.jar;C:\Users\oiio6\.m2\repository\com\vaadin\external\google\android-json\0.0.20131108.vaadin1\android-json-0.0.20131108.vaadin1.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-core\5.3.23\spring-core-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-jcl\5.3.23\spring-jcl-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-test\5.3.23\spring-test-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\xmlunit\xmlunit-core\2.9.0\xmlunit-core-2.9.0.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-data-jpa\2.7.4\spring-boot-starter-data-jpa-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-aop\2.7.4\spring-boot-starter-aop-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\aspectj\aspectjweaver\1.9.7\aspectjweaver-1.9.7.jar;C:\Users\oiio6\.m2\repository\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar;C:\Users\oiio6\.m2\repository\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar;C:\Users\oiio6\.m2\repository\org\hibernate\hibernate-core\5.6.11.Final\hibernate-core-5.6.11.Final.jar;C:\Users\oiio6\.m2\repository\org\jboss\logging\jboss-logging\3.4.3.Final\jboss-logging-3.4.3.Final.jar;C:\Users\oiio6\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\oiio6\.m2\repository\org\jboss\jandex\2.4.2.Final\jandex-2.4.2.Final.jar;C:\Users\oiio6\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.1.2.Final\hibernate-commons-annotations-5.1.2.Final.jar;C:\Users\oiio6\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.6\jaxb-runtime-2.3.6.jar;C:\Users\oiio6\.m2\repository\org\glassfish\jaxb\txw2\2.3.6\txw2-2.3.6.jar;C:\Users\oiio6\.m2\repository\com\sun\istack\istack-commons-runtime\3.0.12\istack-commons-runtime-3.0.12.jar;C:\Users\oiio6\.m2\repository\com\sun\activation\jakarta.activation\1.2.2\jakarta.activation-1.2.2.jar;C:\Users\oiio6\.m2\repository\org\springframework\data\spring-data-jpa\2.7.3\spring-data-jpa-2.7.3.jar;C:\Users\oiio6\.m2\repository\org\springframework\data\spring-data-commons\2.7.3\spring-data-commons-2.7.3.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-orm\5.3.23\spring-orm-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-tx\5.3.23\spring-tx-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-aspects\5.3.23\spring-aspects-5.3.23.jar;C:\Users\oiio6\.m2\repository\com\google\code\gson\gson\2.8.5\gson-2.8.5.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.7.4\spring-boot-starter-jdbc-2.7.4.jar;C:\Users\oiio6\.m2\repository\com\zaxxer\HikariCP\4.0.3\HikariCP-4.0.3.jar;C:\Users\oiio6\.m2\repository\org\springframework\spring-jdbc\5.3.23\spring-jdbc-5.3.23.jar;C:\Users\oiio6\.m2\repository\org\springframework\boot\spring-boot-starter-validation\2.7.4\spring-boot-starter-validation-2.7.4.jar;C:\Users\oiio6\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.65\tomcat-embed-el-9.0.65.jar;C:\Users\oiio6\.m2\repository\org\hibernate\validator\hibernate-validator\6.2.5.Final\hibernate-validator-6.2.5.Final.jar;C:\Users\oiio6\.m2\repository\jakarta\validation\jakarta.validation-api\2.0.2\jakarta.validation-api-2.0.2.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-swagger2\2.9.2\springfox-swagger2-2.9.2.jar;C:\Users\oiio6\.m2\repository\io\swagger\swagger-annotations\1.5.20\swagger-annotations-1.5.20.jar;C:\Users\oiio6\.m2\repository\io\swagger\swagger-models\1.5.20\swagger-models-1.5.20.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.4\jackson-annotations-2.13.4.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-spi\2.9.2\springfox-spi-2.9.2.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-core\2.9.2\springfox-core-2.9.2.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-schema\2.9.2\springfox-schema-2.9.2.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-swagger-common\2.9.2\springfox-swagger-common-2.9.2.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-spring-web\2.9.2\springfox-spring-web-2.9.2.jar;C:\Users\oiio6\.m2\repository\com\google\guava\guava\20.0\guava-20.0.jar;C:\Users\oiio6\.m2\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;C:\Users\oiio6\.m2\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;C:\Users\oiio6\.m2\repository\org\springframework\plugin\spring-plugin-core\1.2.0.RELEASE\spring-plugin-core-1.2.0.RELEASE.jar;C:\Users\oiio6\.m2\repository\org\springframework\plugin\spring-plugin-metadata\1.2.0.RELEASE\spring-plugin-metadata-1.2.0.RELEASE.jar;C:\Users\oiio6\.m2\repository\org\mapstruct\mapstruct\1.2.0.Final\mapstruct-1.2.0.Final.jar;C:\Users\oiio6\.m2\repository\io\springfox\springfox-swagger-ui\2.9.2\springfox-swagger-ui-2.9.2.jar;C:\Users\oiio6\.m2\repository\org\mariadb\jdbc\mariadb-java-client\2.7.3\mariadb-java-client-2.7.3.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit5 com.example.testproject.test.TestLifeCycle
## BeforeAll Annotation 호출 ##
//test1()
## beforeEach Annotation 호출 ##
## test1 시작 ##
## afterEach Annotation 호출 ##
//Test Case 2()
## beforeEach Annotation 호출 ##
## test2 시작 ##
## afterEach Annotation 호출 ##
void com.example.testproject.test.TestLifeCycle.test3() is @Disabled
## afterAll Annotation 호출 ##
Process finished with exit code 0
ProductControllerTest.java
package com.example.testproject.controller;
import com.example.testproject.data.dto.ProductDto;
import com.example.testproject.data.service.Impl.ProductServiceimpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import org.junit.jupiter.api.DisplayName;
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.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
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.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@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 {
//Mockito : 목 객체를 생성하는데 도움을 주는 라이브러리
//given : Mock 객체가 특정 상황에서 해야하는 행위를 정의하는 메소드
//getProduct <- ProductDto값을 리턴해주는 객체이기 때문
given(productService.getProduct("12315")).willReturn(
new ProductDto("15871","pen",5000,2000));
String productId="12315";
// andExpect : 기대하는 값이 나왔는지 체크해볼 수 있는 메소드
mockMvc.perform(
get("/api/v1/product-api/product/"+productId)) //실제로 어떤 통신을 할지에 대해 정의를 해줌
//request를 날리면 json형태의 바디값을 받기때문에 jsonpath를 통해 각각의 값들이 존재하는지 확인함.
.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");
}
// http://localhost:8080/api/v1/product-api/product
@Test
@DisplayName("Product 데이터 생성 테스트")
void createProductTest() throws Exception{
//Mock객체에서 특정 메소드가 실행디는 경우 실제 Return을 줄 수 없기 때문에 아래와 같이 가정사항을 만들어줌
//saveProduct가 호출이 된다면
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();
//json의 형태를 자유롭게 다룰수있게하는 라이브러리
Gson gson=new Gson();
//productDto의 객체를 json으로 변경
String content=gson.toJson(productDto);
//아래 코드로 json 형태 변경 작업 대체할 수 있음
// String json=new ObjectMapper().writeValueAsString(productDto);
mockMvc.perform(post("/api/v1/product-api/product")
.content(content) //어떠한 바디값을 넘겨줄건지
.contentType(MediaType.APPLICATION_JSON)) //타입지정
.andExpect(status().isOk())
.andExpect(jsonPath("$.productId").exists())
.andExpect(jsonPath("$.productName").exists())
.andExpect(jsonPath("$.productPrice").exists())
.andExpect(jsonPath("$.productStock").exists())
.andDo(print());
//saveProduct가 실행되었는지 체크
verify(productService).saveProduct("15871","pen",5000,2000);
}
}
[2022-10-21 19:41:50.702] [INFO ] [main] c.e.t.c.ProductController [ProductController] perform getProduct of Around Hub API.
[2022-10-21 19:41:50.717] [INFO ] [main] c.e.t.c.ProductController [ProductController] Response :: productId = 15871, productName = pen, productPrice = 5000, productStock = 2000, Response Time = 15ms
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/v1/product-api/product/12315
Parameters = {}
Headers = []
Body = null
Session Attrs = {}
Handler:
Type = com.example.testproject.controller.ProductController
Method = com.example.testproject.controller.ProductController#getProduct(String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = 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 = []
[2022-10-21 19:41:51.570] [INFO ] [main] c.e.t.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.example.testproject.controller.ProductController
Method = com.example.testproject.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 = 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 = []
package com.example.testproject.service.Impl;
import com.example.testproject.data.dto.ProductDto;
import com.example.testproject.data.entity.ProductEntity;
import com.example.testproject.data.handler.Impl.ProductDataHandlerImpl;
import com.example.testproject.data.handler.ProductDataHandler;
import com.example.testproject.data.service.Impl.ProductServiceimpl;
import com.example.testproject.data.service.ProductService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.mockito.Mockito.verify;
//어떠한 객체를 가져올지 모르겠을때
//@SpringBootTest(classes={ProductDataHandlerImpl.class, ProductServiceimpl.class})
@ExtendWith(SpringExtension.class)
@Import({ProductDataHandlerImpl.class, ProductServiceimpl.class})
public class ProductServiceImplTest {
//ProductServiceImpl를 보고오기
@MockBean
ProductDataHandlerImpl productDataHandler;
@Autowired
ProductServiceimpl productService;
@Test
public void getProductTest(){
//given
Mockito.when(productDataHandler.getProductEntity("123"))
.thenReturn(new ProductEntity("123","pen",2000,3000));
ProductDto productDto=productService.getProduct("123");
Assertions.assertEquals(productDto.getProductId(), "123");
Assertions.assertEquals(productDto.getProductName(), "pen");
Assertions.assertEquals(productDto.getProductPrice(), 2000);
Assertions.assertEquals(productDto.getProductStock(), 3000);
verify(productDataHandler).getProductEntity("123");
}
@Test
public void saveProductTest() {
//given
Mockito.when(productDataHandler.saveProductEntity("123", "pen", 2000, 3000))
.thenReturn(new ProductEntity("123", "pen", 2000, 3000));
ProductDto productDto = productService.saveProduct("123", "pen", 2000, 3000);
Assertions.assertEquals(productDto.getProductId(), "123");
Assertions.assertEquals(productDto.getProductName(), "pen");
Assertions.assertEquals(productDto.getProductPrice(), 2000);
Assertions.assertEquals(productDto.getProductStock(), 3000);
verify(productDataHandler).saveProductEntity("123","pen",2000,3000);
}
}