반응형
13. 13. 가짜객체 ~ 14. 14. 가게 추가 - 1 ( 가짜 객체 중요)
mock objectmockito 라는 프레임 워크를 이용해 온전히 테스트에 집중하기 위한 가짜 객체( 따라하는) 를 만들 수 있다.
가짜객체를 이용하면, 테스트가 좀더 가벼워지고, 독립적으로 온전히 테스트 할 수 있다.
package com.fastcampus.eatgo.interfaces;
import com.fastcampus.eatgo.application.RestaurantService;
import com.fastcampus.eatgo.domain.*;
import com.fastcampus.eatgo.domain.MenuItem;
import org.junit.Test;
import org.junit.runner.RunWith;
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.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
//스프링을 이용해서 이 테스트를 진행해라.
// 안쓰는 import 정리 ctrl alt o
@RunWith(SpringRunner.class)
@WebMvcTest(RestaurantController.class) //이 컨트롤러를 검사해라.
public class RestaurantControllerTest {
@Autowired
private MockMvc mvc;
//
// // 컨트롤러에 원하는 객체 주입
// @SpyBean(RestaurantRepositoryImpl.class)
// private RestaurantRepository restaurantRepository;
// 가짜 객체 만들기: 의존성 있는 친구들을 진짜 만드는 것이 아니라 가짜로 만들어준다.
@MockBean// 서비스 구현에 불문하고 controller 의 테스트만 온번히 가능
private RestaurantService restaurantService;
// @SpyBean(RestaurantService.class)
// private RestaurantService restaurantService;g
// @SpyBean(MenuItemRepositoryImpl.class)
// private MenuItemRepository menuItemRepository;
@Test
public void list() throws Exception {
List<Restaurant> restaurants = new ArrayList<>();
restaurants.add(new Restaurant(1004L, "Bob zip", "Seoul"));
restaurants.add(new Restaurant(2020L, "Bob2 zip", "Seoul"));
given(restaurantService.getRestaurants()).willReturn(restaurants);// 가짜로 데이터 삽입
mvc.perform(get("/restaurants")).andExpect(status().isOk()).andExpect(content().string(
containsString("\"name\":" +
"\"Bob zip\""))).andExpect(content().string(
containsString("\"id\":" +
"1004")));// 이 데이터에서 문자열 이것이 포함되어있는지 확인
}
@Test
public void detail() throws Exception {
Restaurant restaurant1 = new Restaurant(1004L, "Bob zip", "Seoul");
Restaurant restaurant2 = new Restaurant(2020L, "Bob2 zip", "Seoul");
restaurant1.addMenuItem(new MenuItem("Kimchi"));
given(restaurantService.getRestaurant(1004L)).willReturn(restaurant1);
given(restaurantService.getRestaurant(2020L)).willReturn(restaurant2); // 가짜 객체가 이걸 보내줄 것이다. : given
mvc.perform(get("/restaurants/1004")).andExpect(status().isOk()).andExpect(content().string(
containsString("\"name\":" +
"\"Bob zip\""))).andExpect(content().string(
containsString("\"id\":" +
"1004"))).andExpect(content().string(
containsString("Kimchi")));// 이 데이터에서 문자열 이것이 포함되어있는지 확인
mvc.perform(get("/restaurants/2020")).andExpect(status().isOk()).andExpect(content().string(
containsString("\"name\":" +
"\"Bob2 zip\""))).andExpect(content().string(
containsString("\"id\":" +
"2020")));// 이 데이터에서 문자열 이것이 포함되어있는지 확인
}
}
package com.fastcampus.eatgo.application;
import com.fastcampus.eatgo.domain.*;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.given;
public class RestaurantServiceTest {
private RestaurantService restaurantService;
@Mock //가짜 객체 reposit 말고 직접 온전한 서비스 테스트
private RestaurantRepository restaurantRepository;
@Mock //가짜 객체
private MenuItemRepository menuItemRepository;
// 스프링이 해줄수 없는 작업들을 미리 한다, 예) 서비스와 레포지토리 연결
@Before //모든 테스트 시작전에 반드시 이것을 해본다.
public void setUp() {
MockitoAnnotations.initMocks(this);//가짜객체 초기화들
// restaurantRepository = new RestaurantRepositoryImpl();
// menuItemRepository = new MenuItemRepositoryImpl();
mockRestaurantRespository();
mockMenuItemRespository();
restaurantService = new RestaurantService(restaurantRepository, menuItemRepository);
}
private void mockMenuItemRespository() {
List<MenuItem> menuItems = new ArrayList<>();
menuItems.add(new MenuItem("Kimchi"));
given(menuItemRepository.findAllByRestaurantId(1004L)).willReturn(menuItems);
}
private void mockRestaurantRespository() {
List<Restaurant> restaurants = new ArrayList<>();
Restaurant restaurant1 = new Restaurant(1004L, "Bob zip", "Seoul");
Restaurant restaurant2 = new Restaurant(2020L, "Bob2 zip", "Seoul");
restaurants.add(restaurant1);
restaurants.add(restaurant2);
given(restaurantRepository.findById(1004L)).willReturn(restaurant1);
given(restaurantRepository.findAll()).willReturn(restaurants);
}
@Test
public void getRestaurant() {
Restaurant restaurant = restaurantService.getRestaurant(1004L);
assertThat(restaurant.getId(), is(1004L));
MenuItem menuItem = restaurant.getMenuItems().get(0);
assertThat(menuItem.getName(), is("Kimchi"));
}
@Test
public void getRestaurants() {
List<Restaurant> restaurants = restaurantService.getRestaurants();
assertThat(restaurants.get(0).getId(), is(1004L));
}
}
httpie 에 대해서 배움. 터미널에서 api 테스트가 가능하다.
post 요청의 ok 는 201 이다.
status.isCreated()
http GET localhost:8080
http GET localhost:8080/restaurants/1004
ackage kr.co.fastcampus.eatgo.interfaces;
import kr.co.fastcampus.eatgo.application.RestaurantService;
import kr.co.fastcampus.eatgo.domain.Restaurant;
import kr.co.fastcampus.eatgo.domain.RestaurantNotFoundException;
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 java.util.ArrayList;
import java.util.List;
import static org.hamcrest.core.StringContains.containsString;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@WebMvcTest(RestaurantController.class)
public class RestaurantControllerTests {
@Autowired
private MockMvc mvc;
@MockBean
private RestaurantService restaurantService;
@Test
public void list() throws Exception {
List<Restaurant> restaurants = new ArrayList<>();
restaurants.add(Restaurant.builder()
.id(1004L)
.categoryId(1L)
.name("JOKER House")
.address("Seoul")
.build());
given(restaurantService.getRestaurants()).willReturn(restaurants);
mvc.perform(get("/restaurants"))
.andExpect(status().isOk())
.andExpect(content().string(
containsString("\"id\":1004")
))
.andExpect(content().string(
containsString("\"name\":\"JOKER House\"")
));
}
@Test
public void detailWithExisted() throws Exception {
Restaurant restaurant = Restaurant.builder()
.id(1004L)
.categoryId(1L)
.name("JOKER House")
.address("Seoul")
.build();
given(restaurantService.getRestaurant(1004L)).willReturn(restaurant);
mvc.perform(get("/restaurants/1004"))
.andExpect(status().isOk())
.andExpect(content().string(
containsString("\"id\":1004")
))
.andExpect(content().string(
containsString("\"name\":\"JOKER House\"")
));
}
@Test
public void detailWithNotExisted() throws Exception {
given(restaurantService.getRestaurant(404L))
.willThrow(new RestaurantNotFoundException(404L));
mvc.perform(get("/restaurants/404"))
.andExpect(status().isNotFound())
.andExpect(content().string("{}"));
}
@Test
public void createWithValidData() throws Exception {
given(restaurantService.addRestaurant(any())).will(invocation -> {
Restaurant restaurant = invocation.getArgument(0);
return Restaurant.builder()
.id(1234L)
.categoryId(1L)
.name(restaurant.getName())
.address(restaurant.getAddress())
.build();
});
mvc.perform(post("/restaurants")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"categoryId\":1,\"name\":\"Beryong\"," +
"\"address\":\"Busan\"}"))
.andExpect(status().isCreated())
.andExpect(header().string("location", "/restaurants/1234"))
.andExpect(content().string("{}"));
verify(restaurantService).addRestaurant(any());
}
@Test
public void createWithInvalidData() throws Exception {
mvc.perform(post("/restaurants")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"categoryId\":1,\"name\":\"\",\"address\":\"\"}"))
.andExpect(status().isBadRequest());
}
@Test
public void updateWithValidData() throws Exception {
mvc.perform(patch("/restaurants/1004")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"categoryId\":1,\"name\":\"JOKER Bar\"," +
"\"address\":\"Busan\"}"))
.andExpect(status().isOk());
verify(restaurantService)
.updateRestaurant(1004L, 1L, "JOKER Bar", "Busan");
}
@Test
public void updateWithInvalidData() throws Exception {
mvc.perform(patch("/restaurants/1004")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"categoryId\":1,\"name\":\"\",\"address\":\"\"}"))
.andExpect(status().isBadRequest());
}
@Test
public void updateWithoutName() throws Exception {
mvc.perform(patch("/restaurants/1004")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\":\"\",\"address\":\"Busan\"}"))
.andExpect(status().isBadRequest());
}
}
자바 인강이 듣고 싶다면 =>https://bit.ly/3ilMbIO
반응형
'스프링, 자바' 카테고리의 다른 글
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 49회차 미션 (0) | 2020.09.27 |
---|---|
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 48회차 미션 (0) | 2020.09.26 |
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 46회차 미션 (0) | 2020.09.24 |
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 45회차 미션 (0) | 2020.09.23 |
[패스트캠퍼스 수강 후기] 자바 인강 100% 환급 챌린지 44회차 미션 (0) | 2020.09.22 |