JUnit을 활용한 테스트 코드 작성
리포지토리 객체의 테스트
리포지토리는 JpaRepository를 상속받아 기본적인 쿼리 메소드를 사용할 수 있다.
findById 같은 리포지토리의 기본 메서드는 이미 테스트 검증을 마치고 제공되었으므로 기본 메서드에 대한 테스트는 큰 의미가 없다.
db에 테스트용 데이터가 쌓이면 곤란하다. 그러므로 테스트용 db를 쓰거나 아예 db 연동 없이 테스트 하는 편이 나을 수도 있다.
테스트 폴더 내에 ProductRepositoryTest 를 만들자.
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class ProductRepositoryTest {
@Autowired
private ProductRepository productRepository;
@Test
void save() {
// given
Product product = new Product();
product.setName("펜");
product.setPrice(1000);
product.setStock(1000);
// when
Product savedProduct = productRepository.save(product);
// then
assertEquals(product.getName(), savedProduct.getName());
assertEquals(product.getPrice(), savedProduct.getPrice());
assertEquals(product.getStock(), savedProduct.getStock());
}
}
@DataJapTest 어노테이션은 다음과 같은 기능을 제공한다.
- jpa와 관련된 설정만 로드해서 테스트 진행
- 기본적으로 @Transactional 어노테이션을 포함하고 있어 테스트 코드가 종료되면 자동으로 롤백됨
- 기본값으로 임베디드 데이터베이스 사용
임베디드 데이터베이스 말고 실제 db로 테스트를 진행하고 싶으면 @AutoConfigureTestDatabase 어노테이션 값을 조정하면 된다. 기본값은 Replace.Any 인데 이걸 Replace.None으로 변경하면 실제 사용하는 데이터베이스로 테스트가 가능하다.
위 테스트 코드에 대해 풀이하면,
Given 구문에서 테스트에 사용할 Product 객체를 만들고,
When 구문에서 save를 진행하며,
Then 구문에서 save의 리턴 객체와 Given에서 생성한 엔티티 객체의 값이 일치하는지 assertEquals를 통해 검증한다.
@SpringBootTest
public class ProductRepositoryTest2 {
@Autowired
ProductRepository productRepository;
@Test
public void basicCRUDTest() {
/* create */
// given
Product givenProduct = Product.builder()
.name("노트")
.price(1000)
.stock(500)
.build();
// when
Product savedProduct = productRepository.save(givenProduct);
// then
Assertions.assertThat(savedProduct.getNumber())
.isEqualTo(givenProduct.getNumber());
Assertions.assertThat(savedProduct.getName())
.isEqualTo(givenProduct.getName());
Assertions.assertThat(savedProduct.getPrice())
.isEqualTo(givenProduct.getPrice());
Assertions.assertThat(savedProduct.getStock())
.isEqualTo(givenProduct.getStock());
/* read */
// when
Product selectedProduct = productRepository.findById(savedProduct.getNumber())
.orElseThrow(RuntimeException::new);
// then
Assertions.assertThat(selectedProduct.getNumber())
.isEqualTo(givenProduct.getNumber());
Assertions.assertThat(selectedProduct.getName())
.isEqualTo(givenProduct.getName());
Assertions.assertThat(selectedProduct.getPrice())
.isEqualTo(givenProduct.getPrice());
Assertions.assertThat(selectedProduct.getStock())
.isEqualTo(givenProduct.getStock());
/* update */
// when
Product foundProduct = productRepository.findById(selectedProduct.getNumber())
.orElseThrow(RuntimeException::new);
foundProduct.setName("장난감");
Product updatedProduct = productRepository.save(foundProduct);
// then
assertEquals(updatedProduct.getName(), "장난감");
/* delete */
// when
productRepository.delete(updatedProduct);
// then
assertFalse(productRepository.findById(selectedProduct.getNumber()).isPresent());
}
}
@JpaRepository 대신 @SpringBootTest 어노테이션으로도 테스트를 진행할 수 있다.
참고로 이 코드에서는 crud를 한 번에 테스트하는데, Given 구분은 하나만 작성하고 crud 모두에 활용하였다.
이렇게 하면 스프링의 모든 설정을 가져오고 빈 객체도 전체를 스캔한다.
속도가 느려지므로 다른 방법으로 테스트 할 수 있다면 대안을 고려하는 것이 좋다.
테스트 주도 개발(TDD)
테스트 주도 개발은 테스트 코드를 먼저 작성한 후 테스트를 통과하는 코드를 작성하는 과정을 반복하는 개발 방식이다.
설계 이후 바로 테스트 코드를 작성하고 이후 어플리케이션 코드를 작성하는 식으로 진행되게 된다.
TDD의 장점은 다음과 같다.
디버깅 시간 단축
생산성 향상
재설계 시간 단축
추가 구현이 용이
누가 테스트 코드를 짜주면ㅎ 개발하는 입장에선 정말 편할 것 같다..
하지만 기존 프로세스를 갈아엎기 어렵기 때문에 아직 TDD를 적용한 조직은 많지 않다고 한다.
'개발 관련 공부 > 스프링부트 핵심 가이드' 카테고리의 다른 글
08 Spring Data JPA 활용 (1) | 2024.01.06 |
---|---|
07 테스트 코드 작성하기(2) (0) | 2023.12.24 |
07 테스트 코드 작성하기(1) (1) | 2023.11.12 |
06 데이터베이스 연동(3) (0) | 2023.10.28 |
06 데이터베이스 연동(2) (2) | 2023.10.14 |
댓글