티스토리 뷰
객체의 양방향 관계
객체의 양방향 관계는 사실 양방향 관계가 아니라 서로 다른 단방향 관계 2개다.
객체를 양방향으로 참조하려면 단방향 연관관계를 2개 만들어야한다.
연관관계의 주인(Owner)
양방향 매핑 규칙
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래키를 관리(등록, 수정)
- 주인이 아닌 쪽은 읽기만 가능
- 주인은 mappedBy 속성 사용하지 않음
- 주인이 아니면 mappedBy 속성으로 주인 지정
누구를 주인으로?
외래 키가 있는 곳을 주인으로 정해라.
Entity의 관계를 모두 단방향으로 설정한 후 필요할 때만 양방향 관계를 설정한다.
심화과제 테스트 코드 분석
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class OrderIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
private HttpHeaders headers;
private ObjectMapper mapper = new ObjectMapper();
private RestaurantDto registeredRestaurant;
private FoodDto food1 = FoodDto.builder()
.id(null)
.name("쉑버거 더블")
.price(10900)
.build();
@TestInstance(TestInstance.Lifecycle.PER_CLASS): 테스트 코드의 라이프 사이클은 클래스 기준
@TestMethodOrder(MethodOrderer.OrderAnnotation.class): 테스트 코드의 순서 정하기
@Autowired
private TestRestTemplate restTemplate
: HTTP 요청 후 데이터를 응답 받을 수 있는 템플릿 객체
private HttpHeaders headers;
: HTTP의 헤더 부분 선언
private ObjectMapper mapper = new ObjectMapper();
: 자바 객체를 JSON화 시키는 mapper
private RestaurantDto registeredRestaurant;
: 음식점 등록 Test에서 음식점 등록 성공시 registeredRestaurant에 값 할당
@BeforeEach
public void setup() {
headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
}
@BeforeEach에 HTTP헤더 부분 설정함으로써 테스트 코드에서 보내는 RequestBody의 ContentType은 JSON이라고 명시
@Test
@Order(1)
@DisplayName("음식점1 등록")
void test1() throws JsonProcessingException {
// given
RestaurantDto restaurantRequest = RestaurantDto.builder()
.id(null)
.name("쉐이크쉑 청담점")
.minOrderPrice(5000)
.deliveryFee(1000)
.build();
String requestBody = mapper.writeValueAsString(restaurantRequest);
HttpEntity<String> request = new HttpEntity<>(requestBody, headers);
// when
ResponseEntity<RestaurantDto> response = restTemplate.postForEntity(
"/restaurant/register",
request,
RestaurantDto.class);
// then
assertEquals(HttpStatus.OK, response.getStatusCode());
RestaurantDto restaurantResponse = response.getBody();
assertNotNull(restaurantResponse);
assertTrue(restaurantResponse.id > 0);
assertEquals(restaurantRequest.name, restaurantResponse.name);
assertEquals(restaurantRequest.minOrderPrice, restaurantResponse.minOrderPrice);
assertEquals(restaurantRequest.deliveryFee, restaurantResponse.deliveryFee);
// 음식점 등록 성공 시, registeredRestaurant 에 할당
registeredRestaurant = restaurantResponse;
}
*** void test1() throws JsonProcessingException
: 음식점을 등록하는 test1 메소드는 다른 테스트 class 내부에 있는 것이 아니라 통합 테스트(IntegtationTest)에서 선언된 메소드. @TestInstance(TestInstance.Lifecycle.PER_CLASS)에서 선언한 바와 같이 테스트 코드의 라이프 사이클은 클래스 기준이다. 따라서 테스트마다
Long restaurantId = registeredRestaurant.id;
로 음식점의 Id를 받아오는 것이 가능해짐.
String requestBody = mapper.writeValueAsString(restaurantRequest);
: restaurantRequest를 JSON화 시켜 requestBody에 저장 (throws JsonProcessingException이 필요한 이유)
HttpEntity<String> request = new HttpEntity<>(requestBody, headers);
: requestBody와 Header를 하나로 요청하기 위해서 HttpEntity로 묶는다.
ResponseEntity<RestaurantDto> response = restTemplate.postForEntity(
"/restaurant/register",
request,
RestaurantDto.class);
: restTemplate.postForEntity(url, HttpEntity, response받을 class)
-> postForEntity: HttpEntity를 POST 요청으로 보낸다.
-> ResponseEntity<RestaurantDto> Response받을 class타입
assertEquals(HttpStatus.OK, response.getStatusCode());
RestaurantDto restaurantResponse = response.getBody();
assertEqual / assertNotNull / assertThrow
: 원하는 결과가 일치하는 지 확인하기 위함. (두 값이 같지 않으면 / 값이 null이 아니면 / exception이 나지 않으면 테스트 실패)
ResponseEntitiy.getBody를 함으로써 응답받은 RestaurantDto를 확인할 수 있다.
ResponseEntity<FoodDto[]> response = restTemplate.getForEntity(
"/restaurant/" + restaurantId + "/foods",
FoodDto[].class);
FoodDto food2Response = Arrays.stream(foodsResponse)
.filter(food -> food2.getName().equals(food.getName()))
.findAny()
.orElse(null);
assertNotNull(food2Response);
assertNotNull(food2Response.getId());
assertEquals(food2.getName(), food2Response.getName());
assertEquals(food2.getPrice(), food2Response.getPrice());
음식점의 음식 정보 List를 받고, response받은 음식 정보 List중에서 food2와 같은 이름의 FoodDto가 존재하는지 확인한다.
'TIL(Today I Learn)' 카테고리의 다른 글
WIL 5주차(Week I Learn) (0) | 2022.06.19 |
---|---|
TIL 220609 (0) | 2022.06.09 |
TIL 220603 (0) | 2022.06.03 |
TIL 220603 (0) | 2022.06.03 |
TIL 220602 (0) | 2022.06.02 |