🖤인프런만의 100% 블프 이벤트🖤

🎁100% 환급+할인+당첨 가능한 인프런 블프 구경오세요!

[워밍업 클럽 스터디 2기 - BE] (클린코드, 테스트코드) day 15 미션

[워밍업 클럽 스터디 2기 - BE] (클린코드, 테스트코드) day 15 미션

 

출처 : 인프런 워밍업 클럽 스터디 2기 - 백엔드 클린코드, 테스트 코드(Java, Spring Boot)

Practical Testing: 실용적인 테스트 가이드

 

Layered Architecture

 

image

핵심은 관심사의 분리. 역할을 나누어 유지보수성을 늘린다.

 

Persistence Layer

  • 데이터와 DB가 만나는 계층

  • JPA, MyBatis 등등 결국 최종 쿼리를 DB로 전달해야 함.

  • 이 계층은 DB에 쿼리를 전달하는 역할만 해야지 여기서 뭔가 데이터를 가공한 후에 쿼리를 만들면 안됨.

    • 데이터 가공은 비즈니스 계층에서 하는 것이 바람직하다고 생각.

  • 테스트 시 스프링 컨테이너를 사용하지만 쿼리 자체를 테스트하는 것이기 때문에 단위 테스트 성격을 띈다.

테스트 방법

  • @SpringBootTest를 사용 시 @Transaction이 없기 때문에 tearDown()을 구현

  • @DataJpaTest 사용 시 @Transaction이 있기 때문에 이에 따른 트랜잭션 전파를 잘 고려해서 판단해야 함.

    • 이걸 고려하지 않고 테스트 작성 시 테스트는 잘 통과하는데 실제로는 안될 수도 있음.

  • 테스트 시 샘플 객체를 만들어서 저장 후 (`given`) 테스트할 메서드를 호출 (`when`)

  • 검증(`then`)시 단일 객체라면 그냥 비교하면 되는데, List같은 자료구조에 담긴 여러 객체라면

    • 1. 먼저 사이즈를 체크

    • 2. extracting()으로 검사할 항목 체크

    • 3. contains*() + tuple(데이터)로 비교

@Test
@DisplayName("원하는 판매상태를 가진 상품들을 조회한다.")
void findAllBySellingStatusIn() {
	// given
	Product product1 = createProduct("001", HANDMADE, SELLING, "아메리카노", 4000);
	Product product2 = createProduct("002", HANDMADE, HOLD, "카페라떼", 4500);
	Product product3 = createProduct("003", HANDMADE, STOP_SELLING, "팥빙수", 7000);

	productRepository.saveAll(List.of(product1, product2, product3));
	// when
	List<Product> products = productRepository.findAllBySellingStatusIn(List.of(SELLING, HOLD));

	// then
	assertThat(products).hasSize(2)
			.extracting("productNumber", "name", "sellingStatus")
			.containsExactlyInAnyOrder(
					tuple("001", "아메리카노", SELLING),
					tuple("002", "카페라떼", HOLD)
			);
}

 

Business Layer

  • 핵심적인 비즈니스 로직을 처리하는 계층

  • Persistence Layer와 상호작용한다.

  • 트랜잭션이 보장되어야 한다.

테스트 방법

  • Persistence Layer를 묶어서 통합 테스트

  • Persistence LayerMocking 해서 단위 테스트

  • Business Layer는 트랜잭션이 중요하기 때문에 테스트시에도 이에 따른 트랜잭션 전파를 잘 고려해서 판단 해야 함.

 

 

Presentation Layer

  • 클라이언트로부터 데이터를 받아 Business Layer로 요청을 넘기는 계층

  • 데이터에 대한 기본적인 검증을 수행 (필수 입력 값, 데이터 타입, null 등)

  • Business Layer로부터 받은 데이터를 사용자에게 반환

  • Business LayerPresentation Layer를 모르도록 설계하면 좋다.

    • Business Layer에 클라이언트에게 받은 데이터를 바로 넘기는 것 보다 서비스 전용 DTO로 래핑해서 넘기기.

  • 클라이언트에게 값을 넘겨줄 때는 정해진 포맷(errorCode, message, data 등)으로 넘겨주는 것이 좋다.

테스트 방법

  • 데이터에 대한 기본적인 검증을 수행

  • Business Layer는 Mocking해서 테스트 진행

  • mockMvc를 활용하여 Http 응답에 대한 검증을 진행한다.

@Test
@DisplayName("신규 주문을 등록한다.")
void createOrder() throws Exception {
	// given
	OrderCreateRequest request = OrderCreateRequest.builder()
			.productNumbers(List.of("001"))
			.build();

	// when // then
	mockMvc.perform(post("/api/v1/orders/new")
					.content(objectMapper.writeValueAsString(request))
					.contentType(MediaType.APPLICATION_JSON)
			)
			.andDo(print())
			.andExpect(status().isOk())
			.andExpect(jsonPath("$.code").value("200"))
			.andExpect(jsonPath("$.status").value("OK"))
			.andExpect(jsonPath("$.message").value("OK"));

}

 

 

댓글을 작성해보세요.

채널톡 아이콘