본문 바로가기
개발 관련 공부/스프링부트 핵심 가이드

07 테스트 코드 작성하기(3)

by 슴새 2023. 12. 31.
반응형

 

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)

테스트 주도 개발은 테스트 코드를 먼저 작성한 후 테스트를 통과하는 코드를 작성하는 과정을 반복하는 개발 방식이다.

 

출처 https://medium.com/@yyuni915/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%A3%BC%EB%8F%84-%EA%B0%9C%EB%B0%9C-c9341fad33d0

설계 이후 바로 테스트 코드를 작성하고 이후 어플리케이션 코드를 작성하는 식으로 진행되게 된다.

 

TDD의 장점은 다음과 같다.

디버깅 시간 단축

생산성 향상

재설계 시간 단축

추가 구현이 용이

 

누가 테스트 코드를 짜주면ㅎ 개발하는 입장에선 정말 편할 것 같다..

하지만 기존 프로세스를 갈아엎기 어렵기 때문에 아직 TDD를 적용한 조직은 많지 않다고 한다.

 

 

반응형

댓글