3주차 회고록-Readable Code & Practical Testing
테스트 코드 적용실습-테스트코드와 함께 지난 시간 리팩토링을 같이 하고싶어 욕심을 냈다그러다 뒤에 practical-testing 분량을 한참바야한다는 것을 몰랐다가 나중에서야 알고나서 미션을 내기에 욕심과 잘못된 착각에 낼수가 없었다. 처음 for반복문에서 두번째 foreach를 따라하며 고민하고 좌절하며 따라하고 만들어보니 지난날 그냥 인강으로 볼때보다 이해와 흡수가 잘 되었다. 세번째로 stream이 아주 달리 보였다.자연스럽게 stream 을 쓸때에는 그에대한 클래스나 메서드가 완성되었을때는 사용할수 있었다. public List<ProductResponse> getSellingProducts() { List<Product> products=productRepository.findAllBySellingTypeIn(ProductSellingType.forDisplay()); return products.stream() .map(ProductResponse::of) .collect(Collectors.toList()); } 테스트 케이스에 따른 세분화하기테스트를 하면서도 어떻게 무엇을 써야할지 몰라 망설인다 우왕좌왕 하면서도 assertThat 써야하는곳의 전개과정을 보며 어떻게 돌아가는지 흐름과 진짜 반대로 버그가 일어날 만한 상황을 역으로 확인하는 부분에서 이해할 수 있었다.형식적인 테스트 부터 시작하여 경계값설정테스트는 소비자 입장에서 생각해볼 수 있는 부분이다@Test void addZeroBeverages(){ CafeKiosk cafeKiosk=new CafeKiosk(); Americano americano=new Americano(); assertThatThrownBy(()-> cafeKiosk.add(americano,0)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("음료는 1잔 이상 주문하실 수 있습니다."); }난 예외처리를 던지는건 알겠는데 () -> 이게 표현이 다소 생소하였다. 값을 반환할때 저렇게 쓴다는걸 우테코유트브를 보다 알았다 나한테 아주 요상하게 생긴 녀석이었다 머야 괄호를 던지나???? assertThatThrownBy(()-> cafeKiosk.add(americano,0)) DisplayName 은 섬세하게 displayName을 굳이 왜써야하나 생각해보았다한글이 지원되어 무엇보다 도메인사용에 대해 이해할수 있게 명확하게 쓰기 최적의 명령어였다.모르는 사람이 바도 테스트의 목적을 이해를 돕는 문서의 결과가 될수 있다는 생각에 공감이 간다.-백날 영어쓰고 설명이 없다면 진짜 영어로 바도 이해가 쉽다면 상관없다. 그러나 만드는 개발자도, 기획자도 관리 유지에 있어 모호한 부분의 확장에선 둘다 필요하다 Spring Jpa & persistence Layer 포트폴리오를 만들기위해 애썼던 지난 시간들이 떠올랐다. 당시도 작년도 난 눈앞에 내용을 쳐내려가기 바빴다 영속성관계를 깊이 있게 보질 못했다. 이번에 보다 보지못한 지나쳤던 부분을 이해하게 되었다.@OneToMany(mappedBy="order")이 어노테이션은 양방향 관계에서 사용되며 mappedBy 는 주체가 아닌쪽에서 관계를 관리하는 필드를 지정한다@Entity public class Order { @Id private Long id; @OneToMany(mappedBy = "order") private List<OrderItem> items; } @Entity public class OrderItem { @Id private Long id; @ManyToOne @JoinColumn(name = "order_id") private Order order; }@MapsId 와 @OneToOne(일대일관계)@OneToOne 두 엔티티 간의 일대일 관계를 정의한다 @MapsId@OneToOne 관계에서 같이 사용되며 두개체가 동일한 기본키를 공유할 때 그 관계를 설정하는데 사용된다@Entity public class UserProfile { @Id private Long id; @OneToOne @MapsId private User user; }아주 비슷하게 생겨서 처음엔 헷갈렸는데 영어보구 알았다. 눈을 크게 뜨고 바야겠다. @SpringBoot VS @ DataJpaTest@DataJpaTest-DataJpaTest 관련 기능중에 @Transactional 기능이 포함되어 rollback 기능이 되어 완료후 초기화를 할 필요하 없다는 사실은 나에게 새삼 놀라웠다. 우라질....Transactional 에 rollback 기능이 있다는것은 알고 있었다 그런데 그 뿌리가 @DataJpaTest 안에도 포함된 내용인지는 새롭게 알았다import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.transaction.annotation.Transactional; import static org.assertj.core.api.Assertions.assertThat; @DataJpaTest @Transactional public class OrderRepositoryTest { @Autowired private OrderRepository orderRepository; @Test public void testSaveOrder() { Order order = new Order(); order.setProductName("Test Product"); order.setQuantity(1); orderRepository.save(order); // 데이터베이스에서 주문을 조회하여 확인 Order foundOrder = orderRepository.findById(order.getId()).orElse(null); assertThat(foundOrder).isNotNull(); assertThat(foundOrder.getProductName()).isEqualTo("Test Product"); } } @Transanctional 과 @ SpringBoot (일반적인 로직) SpringBoot 는 Transactional 과 같이 있을경우에는 rollback기능이 작용한다import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class OrderService { private final OrderRepository orderRepository; public OrderService(OrderRepository orderRepository) { this.orderRepository = orderRepository; } @Transactional public void createOrder(Order order) { // 주문 생성 로직 orderRepository.save(order); // 추가적인 비즈니스 로직 } } 한시간 강의를 듣는데도 정리하고 이해하는데 4-5시간이 걸려 후딱갔다 나한테는 너무 많은 강의량에 눈이 빠질거같다..머리에 구멍난 부분은 차곡차곡 정리되어 가는데 다른분들은 그 많은 강의를 듣고도 스터디에 올려서 난 그러고도 분량이 한참 남아 올리지를 못했다. 내가 하고 싶은 욕심과 내가 소화할 수 있는 부분에 대한 분량에 대해서 시간제한, 자원배분에 대해 생각해보는 한주였다. 참고사항강의 practical testing -박우빈 코치님우테코 람다,오브젝트 유트브-저 닉네임 또 까먹었습니다. 죄송합니다.