기존의 레파지토리들은 일종의 컬렉션과 같은 역할을 했다고한다면 우리는 지금까지했던 복잡한 과정들이 한꺼번에 일어나는 새로운 객체를 Service로 만들것이다.
그리고 컨트롤러에서 기존의 레파지토리들은 삭제할것이다.
/test/~/interfaces/RestaurantControllerTest.java
package kr.co.fastcampus.eatgo.interfaces;
import kr.co.fastcampus.eatgo.application.RestaurantService;
import kr.co.fastcampus.eatgo.domain.MenuItemRepository;
import kr.co.fastcampus.eatgo.domain.MenuItemRepositoryImpl;
import kr.co.fastcampus.eatgo.domain.RestaurantRepository;
import kr.co.fastcampus.eatgo.domain.RestaurantRepositoryImpl;
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.SpyBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.hamcrest.core.StringContains.containsString;
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;
@RunWith(SpringRunner.class) // api 요청처리 테스트를 해주기위한 스프링자체의 어노테이션
@WebMvcTest(RestaurantController.class) // 특정 컨트롤러를 테스트해준다는것을 명시하는 어노테이션
public class RestaurantControllerTest {
@Autowired
private MockMvc mvc; // MockMvc생성
@SpyBean(RestaurantService.class) // service 테스트
private RestaurantService restaurantService;
@SpyBean(RestaurantRepositoryImpl.class) // 일단은 테스트에서는 남겨놓는다
private RestaurantRepository restaurantRepository;
@SpyBean(MenuItemRepositoryImpl.class) // 일단은 테스트에서는 남겨놓는다
private MenuItemRepository menuItemRepository;
@Test
public void list() throws Exception {
mvc.perform(get("/restaurants"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("\"id\":1004")))
.andExpect(content().string(containsString("\"name\":\"Bob zip\"")));
}
@Test
public void detail() throws Exception {
mvc.perform(get("/restaurants/1004"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("\"id\":1004")))
.andExpect(content().string(containsString("\"name\":\"Bob zip\"")))
.andExpect(content().string(
containsString(("Kimchi")) // 메뉴추가 테스트
));
mvc.perform(get("/restaurants/2020"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("\"id\":2020")))
.andExpect(content().string(containsString("\"name\":\"Cyber Food\"")));
}
}
/main/~/interfaces/RestaurantController.java
package kr.co.fastcampus.eatgo.interfaces;
import kr.co.fastcampus.eatgo.application.RestaurantService;
import kr.co.fastcampus.eatgo.domain.MenuItem;
import kr.co.fastcampus.eatgo.domain.MenuItemRepository;
import kr.co.fastcampus.eatgo.domain.Restaurant;
import kr.co.fastcampus.eatgo.domain.RestaurantRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class RestaurantController {
@Autowired
private RestaurantService restarantService; // 기존의 레파지토리를 삭제하고 RestaurantService로 기능을 통합하였다.
@GetMapping("/restaurants") // 가게목록 반환 api
public List<Restaurant> list(){
List<Restaurant> restaurants = restarantService.getRestaurants();
return restaurants;
}
@GetMapping("/restaurants/{id}") // 특정 가게상세 반환 api
public Restaurant detail(@PathVariable("id") Long id){
Restaurant restaurant = restarantService.getRestaurant(id); // 가게의 기본정보 + 메뉴 정보를 반환하는 기능능
return restaurant;
}
}
/test/~/application/RestaurantServiceTest.java 생성
package kr.co.fastcampus.eatgo.application;
import kr.co.fastcampus.eatgo.domain.*;
import org.junit.Before;
import org.junit.Test;
import java.util.List;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;
public class RestaurantServiceTest {
private RestaurantService restaurantService;
private RestaurantRepository restaurantRepository;
private MenuItemRepository menuItemRepository;
@Before // 모든 테스트가 실행되기전 이 어노테이션이 붙은 테스트가 먼저 실행되고 다음 테스트가 실행된다
public void setUp(){
restaurantRepository = new RestaurantRepositoryImpl();
menuItemRepository = new MenuItemRepositoryImpl();
restaurantService = new RestaurantService(restaurantRepository, menuItemRepository);
}
@Test
public void getRestaurants(){
List<Restaurant> restaurants = restaurantService.getRestaurants();
Restaurant restaurant = restaurants.get(0);
assertThat(restaurant.getId(), is(1004L));
}
@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"));
}
}
/main/~/application/RestaurantService.java 생성
package kr.co.fastcampus.eatgo.application;
import kr.co.fastcampus.eatgo.domain.MenuItem;
import kr.co.fastcampus.eatgo.domain.MenuItemRepository;
import kr.co.fastcampus.eatgo.domain.Restaurant;
import kr.co.fastcampus.eatgo.domain.RestaurantRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service // 서비스를 지정하는 어노테이션
public class RestaurantService {
@Autowired
RestaurantRepository restaurantRepository;
@Autowired
MenuItemRepository menuItemsRepository;
public RestaurantService(RestaurantRepository restaurantRepository,
MenuItemRepository menuItemRepository) {
this.restaurantRepository = restaurantRepository;
this.menuItemsRepository = menuItemRepository;
}
public List<Restaurant> getRestaurants() { //가게목록 반환
List<Restaurant> restaurants = restaurantRepository.findAll();
return restaurants;
}
public Restaurant getRestaurant(Long id){ // 특정 가게 반환
Restaurant restaurant = restaurantRepository.findById(id); // 요청되는 id에 따른 특정 가게 반환
List<MenuItem> menuItems = menuItemsRepository.findAllByRestaurantId(id); // 요청되는 id에 따른 가게 메뉴목록 반환
restaurant.setMenuItems(menuItems); // 특정가게의 메뉴목록들 추가
return restaurant;
}
}