1. 단위 테스트
- 단위 테스트는 프로그램을 작은 단위로 쪼개서 각 단위가 정확하게 동작하는지 검사하는 것이다. 이를 통해 문제 발생 시 정확하게 어느 부분이 잘못되었는지를 재빨리 확인할 수 있다.
- JUnit을 사용하여 단위 테스트를 할 수 있다.
다음은 Product 클래스가 잘 동작하는지 확인하기 위한 단위 테스트 코드이다. 상품이 잘 저장되는지 확인할 수 있다.
given 에 저장할 정보를 입력하고, when 에서 상품을 저장한다. then 에서 상품이 잘 저장이 됐는지 확인한다.
class ProductTest {
@Test
@DisplayName("정상 케이스")
void createProduct_Normal() {
// given
Long userId = 100L;
String title = "오리온 꼬북칩 초코츄러스맛 160g";
String image = "https://shopping-phinf.pstatic.net/main_2416122/24161228524.20200915151118.jpg";
String link = "https://search.shopping.naver.com/gate.nhn?id=24161228524";
int lprice = 2350;
ProductRequestDto requestDto = new ProductRequestDto(
title,
image,
link,
lprice
);
// when
Product product = new Product(requestDto, userId);
// then
assertNull(product.getId());
assertEquals(userId, product.getUserId());
assertEquals(title, product.getTitle());
assertEquals(image, product.getImage());
assertEquals(link, product.getLink());
assertEquals(lprice, product.getLprice());
assertEquals(0, product.getMyprice());
}
}
2. Mock Object (가짜 객체)
- "모의, 가짜의"라는 뜻으로 테스트할 때 필요한 실제 객체와 동일한 모의 객체를 만들어 테스트의 효용성을 높이기 위해 사용한다. 이상적으로, 각 테스트 케이스는 서로 분리되어야 하므로 Mock Object를 사용하는 것이 좋다.
- Mockito Framework 는 Mock Object를 쉽게 만들 수 있도록 도와준다.
다음은 Mock Object를 사용한 단위 테스트 코드이다. Mockito 를 사용하기 위해서는 꼭! @ExtendWith 로 사용한다는 것을 알려주어야 한다. ProductRepository를 Mock Object로 사용하기 위해 @Mock을 붙인다.
@ExtendWith(MockitoExtension.class) // 테스트 클래스가 Mockito를 사용함
class ProductServiceTest {
@Mock // Mock Object로 사용할 객체
ProductRepository productRepository;
@Test
@DisplayName("updateProduct() 에 의해 관심 가격이 3만원으로 변경되는지 확인")
void updateProduct_Normal() {
// given
Long productId = 100L;
int myprice = 30000;
ProductMypriceRequestDto requestMyPriceDto = new ProductMypriceRequestDto(
myprice
);
Long userId = 12345L;
ProductRequestDto requestProductDto = new ProductRequestDto(
"오리온 꼬북칩 초코츄러스맛 160g",
"https://shopping-phinf.pstatic.net/main_2416122/24161228524.20200915151118.jpg",
"https://search.shopping.naver.com/gate.nhn?id=24161228524",
2350
);
Product product = new Product(requestProductDto, userId);
ProductService productService = new ProductService(productRepository);
when(productRepository.findById(productId))
.thenReturn(Optional.of(product));
// when
Product result = productService.updateProduct(productId, requestMyPriceDto);
// then
assertEquals(myprice, result.getMyprice());
}
}
3. 통합 테스트
- 여러 개의 단위 테스트들이 서로 연결되어 잘 동작하는지 확인하기 위해서는 통합테스트가 필요하다.
- 통합테스트는 스프링부트가 제공해주는데 @SpringBootTest 어노테이션을 붙이면 된다.
- @Order() 를 통해 테스트 순서를 정할 수 있다.
다음은 통합테스트 코드이다. 통합테스트는 신규 관심상품 등록 -> 신규 등록된 관심상품의 희망 최저가 변경 -> 회원Id로 등록된 모든 관심상품 조회 순으로 이루어진다.
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class ProductIntegrationTest {
@Autowired
ProductService productService;
Long userId = 100L;
Product createdProduct = null;
int updatedMyPrice = -1;
@Test
@Order(1)
@DisplayName("신규 관심상품 등록")
void test1() {
// given
String title = "Apple <b>에어팟</b> 2세대 유선충전 모델 (MV7N2KH/A)";
String imageUrl = "https://shopping-phinf.pstatic.net/main_1862208/18622086330.20200831140839.jpg";
String linkUrl = "https://search.shopping.naver.com/gate.nhn?id=18622086330";
int lPrice = 77000;
ProductRequestDto requestDto = new ProductRequestDto(
title,
imageUrl,
linkUrl,
lPrice
);
// when
Product product = productService.createProduct(requestDto, userId);
// then
assertNotNull(product.getId());
assertEquals(userId, product.getUserId());
assertEquals(title, product.getTitle());
assertEquals(imageUrl, product.getImage());
assertEquals(linkUrl, product.getLink());
assertEquals(lPrice, product.getLprice());
assertEquals(0, product.getMyprice());
createdProduct = product;
}
@Test
@Order(2)
@DisplayName("신규 등록된 관심상품의 희망 최저가 변경")
void test2() {
// given
Long productId = this.createdProduct.getId();
int myPrice = 70000;
ProductMypriceRequestDto requestDto = new ProductMypriceRequestDto(myPrice);
// when
Product product = productService.updateProduct(productId, requestDto);
// then
assertNotNull(product.getId());
assertEquals(userId, product.getUserId());
assertEquals(this.createdProduct.getTitle(), product.getTitle());
assertEquals(this.createdProduct.getImage(), product.getImage());
assertEquals(this.createdProduct.getLink(), product.getLink());
assertEquals(this.createdProduct.getLprice(), product.getLprice());
assertEquals(myPrice, product.getMyprice());
this.updatedMyPrice = myPrice;
}
@Test
@Order(3)
@DisplayName("회원이 등록한 모든 관심상품 조회")
void test3() {
// given
// when
List<Product> productList = productService.getProducts(userId);
// then
// 1. 전체 상품에서 테스트에 의해 생성된 상품 찾아오기 (상품의 id 로 찾음)
Long createdProductId = this.createdProduct.getId();
Product foundProduct = productList.stream()
.filter(product -> product.getId().equals(createdProductId))
.findFirst()
.orElse(null);
// 2. Order(1) 테스트에 의해 생성된 상품과 일치하는지 검증
assertNotNull(foundProduct);
assertEquals(userId, foundProduct.getUserId());
assertEquals(this.createdProduct.getId(), foundProduct.getId());
assertEquals(this.createdProduct.getTitle(), foundProduct.getTitle());
assertEquals(this.createdProduct.getImage(), foundProduct.getImage());
assertEquals(this.createdProduct.getLink(), foundProduct.getLink());
assertEquals(this.createdProduct.getLprice(), foundProduct.getLprice());
// 3. Order(2) 테스트에 의해 myPrice 가격이 정상적으로 업데이트되었는지 검증
assertEquals(this.updatedMyPrice, foundProduct.getMyprice());
}
}
'Back-end > Spring' 카테고리의 다른 글
[SpringBoot] 10주차 스터디(AOP, 트랜잭션) (0) | 2021.10.23 |
---|---|
[SpringBoot] 9주차 스터디 (페이징, JPA 연관관계) (0) | 2021.10.17 |
[SpringBoot] 7주차 스터디 ② (OAuth, 카카오 로그인) (0) | 2021.10.02 |
[SpringBoot] 7주차 스터디 ① (스프링 시큐리티) (0) | 2021.10.02 |
[SpringBoot] 6주차 스터디(객체 지향, DI) (0) | 2021.09.23 |