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 -박우빈 코치님
우테코 람다,오브젝트 유트브
-저 닉네임 또 까먹었습니다. 죄송합니다.
댓글을 작성해보세요.