다음을 수행하여 단위 테스트 코드를 작성하고 테스트를 실행합니다.
STS에서 src/test/java 하위에 있는 io.infograb.order.controller
패키지(package)를 선택합니다.
File > New > Class를 선택한 다음, Name 필드에 OrderControllerTest
을 입력하고 Finish 버튼을 클릭합니다.
OrderControllerTest.java
파일 내용을 아래와 같이 수정합니다.
package io.infograb.order.controller;
import static org.hamcrest.CoreMatchers.is;
import static org.mockito.BDDMockito.given;
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;
import org.junit.jupiter.api.BeforeEach;
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.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import io.infograb.order.service.OrderService;
@DisplayName("Test OrderController")
@WebMvcTest(OrderController.class)
public class OrderControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private WebApplicationContext context;
@MockBean
private OrderService orderService;
@BeforeEach
public void setUp() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(context)
.addFilters(new CharacterEncodingFilter("UTF-8", true))
.alwaysDo(print())
.build();
}
@DisplayName("Should order successfully")
@Test
public void shouldOrder() throws Exception {
// given
given(orderService.orderDrink("user01", 3)).willReturn(true);
// when
final ResultActions actions = this.mockMvc.perform(post("/orders?userId=user01&menuId=3")
.contentType(MediaType.APPLICATION_JSON));
// then
actions.andExpect(status().isOk())
.andExpect(jsonPath("$.message", is("주문이 완료되었습니다.")));
}
@DisplayName("Should return fail message when not enough balance")
@Test
public void shouldReturnFailMessageWhenNotEnoughBalance() throws Exception {
// given
given(orderService.orderDrink("user01", 3)).willReturn(true);
given(orderService.orderDrink("user01", 3)).willReturn(false);
// when
final ResultActions actions = this.mockMvc.perform(post("/orders?userId=user01&menuId=3")
.contentType(MediaType.APPLICATION_JSON));
// then
actions.andExpect(status().isOk())
.andExpect(jsonPath("$.message", is("잔액이 부족합니다.")));
}
}
io.infograb.order.service
패키지에 OrderServiceTest.java
파일을 생성하고 아래와 같이 수정합니다.
package io.infograb.order.service;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.BDDMockito.given;
import org.junit.jupiter.api.DisplayName;
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 io.infograb.order.mapper.MenuMapper;
import io.infograb.order.mapper.UserMapper;
import io.infograb.order.model.Menu;
import io.infograb.order.model.User;
@DisplayName("Test OrderService")
@ExtendWith(MockitoExtension.class)
public class OrderServiceTest {
@InjectMocks
private OrderService orderService;
@Mock
private UserMapper userMapper;
@Mock
private MenuMapper menuMapper;
@DisplayName("Should return true if order successful")
@Test
public void shouldOrderSuccessful() throws Exception {
// given
User user = new User();
user.setId("user01");
user.setName("홍길동");
user.setPhone("010-1234-5678");
user.setEmail("gdhong@infograb.dev");
user.setUseNickname(true);
user.setNickname("신출귀몰");
user.setBalance(10000);
user.setRewards(0);
Menu menu = new Menu();
menu.setId(1);
menu.setName("아이스 카페 아메리카노");
menu.setEnglishName("Iced Caffe Americano");
menu.setPrice(4100);
given(userMapper.selectUserById("user01")).willReturn(user);
given(menuMapper.selectMenuById(1)).willReturn(menu);
// when
boolean expectedResult = orderService.orderDrink("user01", 1);
// then
assertTrue(expectedResult);
}
@DisplayName("Should return false when not enough balance")
@Test
public void shouldBeFailedOrder() throws Exception {
// given
User user = new User();
user.setId("user01");
user.setName("홍길동");
user.setPhone("010-1234-5678");
user.setEmail("gdhong@infograb.dev");
user.setUseNickname(true);
user.setNickname("신출귀몰");
user.setBalance(4000);
user.setRewards(0);
Menu menu = new Menu();
menu.setId(3);
menu.setName("아이스 카페 모카");
menu.setEnglishName("Iced Caffe Mocha");
menu.setPrice(5100);
given(userMapper.selectUserById("user01")).willReturn(user);
given(menuMapper.selectMenuById(3)).willReturn(menu);
// when
boolean expectedResult = orderService.orderDrink("user01", 3);
// then
assertFalse(expectedResult);
}
}
io.infograb.order.mapper
패키지에 UserMapperTest.java
파일을 생성하고 아래와 같이 수정합니다.
package io.infograb.order.mapper;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
import org.springframework.beans.factory.annotation.Autowired;
import io.infograb.order.model.User;
@DisplayName("Test UserMapperTest")
@MybatisTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@DisplayName("Should return user")
@Test
public void shouldReturnUser() {
User user = userMapper.selectUserById("user01");
assertNotNull(user, "User was not found");
assertEquals(user.getId(), "user01");
assertEquals(user.getName(), "홍길동");
assertEquals(user.getPhone(), "010-1234-5678");
assertEquals(user.getEmail(), "gdhong@infograb.dev");
assertTrue(user.isUseNickname());
assertEquals(user.getNickname(), "신출귀몰");
}
@DisplayName("Should return Null if user ID does not exit")
@Test
void shouldUserNotFound() {
User user = userMapper.selectUserById("mark85");
assertNull(user, "User should not be found");
}
}
터미널에서 mvn clean test
명령을 실행하여 단위 테스트 결과를 확인합니다.
mvn clean test
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< io.infograb.order:siren-order-api >------------------
[INFO] Building Siren Order REST API 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ siren-order-api ---
[INFO] Deleting /Users/jason/Library/Mobile Documents/com~apple~CloudDocs/Workspace/siren-order-api/target
[INFO]
[INFO] --- maven-resources-plugin:3.2.0:resources (default-resources) @ siren-order-api ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] Copying 1 resource
[INFO] Copying 6 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ siren-order-api ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 9 source files to /Users/jason/Library/Mobile Documents/com~apple~CloudDocs/Workspace/siren-order-api/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.2.0:testResources (default-testResources) @ siren-order-api ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Using 'UTF-8' encoding to copy filtered properties files.
[INFO] skip non existing resourceDirectory /Users/jason/Library/Mobile Documents/com~apple~CloudDocs/Workspace/siren-order-api/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ siren-order-api ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to /Users/jason/Library/Mobile Documents/com~apple~CloudDocs/Workspace/siren-order-api/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ siren-order-api ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
(생략)
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.438 s - in io.infograb.order.controller.OrderControllerTest
[INFO] Running io.infograb.order.service.OrderServiceTest
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.041 s - in io.infograb.order.service.OrderServiceTest
[INFO] Running io.infograb.order.service.MenuServiceTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 s - in io.infograb.order.service.MenuServiceTest
2021-05-07 17:48:55.957 INFO 38829 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
2021-05-07 17:48:55.957 INFO 38829 --- [extShutdownHook] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor'
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 10, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.957 s
[INFO] Finished at: 2021-05-07T17:48:56+09:00
[INFO] ------------------------------------------------------------------------