inblog logo
|
soultree
    SpringJava

    [Spring] JUnit과 AssertJ로 테스트 코드 작성하기

    Spring에서 주로 사용하는 JUnit과 AssertJ를 왜, 어떻게 사용하는 지 예시 코드를 통해 살펴보자.
    Hi's avatar
    Hi
    Apr 20, 2024
    [Spring] JUnit과 AssertJ로 테스트 코드 작성하기
    Contents
    ✅ 들어가기 전에✅ JUnit이란?JUnit의 특징코드 예시Given-When-Then Pattern✅ AssertJ로 검증문 수정하기
     

    ✅ 들어가기 전에

    테스트 코드를 작성하는 이유가 무엇일까?
    개발 단계에서 테스트 코드를 작성하는 이유는 정말 다양할 것이다. 그 중에서도 가장 손꼽히는 이유는:
    • 개발 과정에서 문제를 미리 예측 및 발견할 수 있다.
    • 애플리케이션을 직접 가동해서 테스트하는 것보다 테스트를 빠르게 진행할 수 있다.
    • 단위 테스트를 통해 각각의 기능 별 테스트가 가능하다.
    • 코드가 작성된 목적을 명확하게 표현할 수 있으며, 불필요한 내용이 추가되는 것을 방지한다.
    • 버그를 미리 발견하여 리팩토링의 리스크가 줄어든다.
     
    📋
    스프링 부트는 애플리케이션을 테스트하기 위한 도구와 어노테이션을 제공한다. 아래와 같은 여러 테스트 도구가 spring-boot-starter-test에 들어있다.
     
    • JUnit
      • 자바 프로그래밍 언어용 단위 테스트 프레임워크
    • Spring Test & Spring Boot Test
      • 스프링 부트 애플리케이션을 위한 통합 테스트 지원
    • AssertJ
      • 검증문인 어설션을 작성하는 데 사용
    • Hamcrest
      • 표현식을 보다 이해하기 쉽게 만드는 데 사용되는 Matcher 라이브러리
    • Mockito
      • 테스트에 사용할 가짜 객체인 mock 객체를 쉽게 만들고, 관리하고, 검증할 수 있게 지원하는 테스트 프레임워크
    • JSONassert
      • JSON 용 어설션 라이브러리
    • JsonPath
      • JSON 데이터에서 특정 데이터를 선택하고 검색하기 위한 라이브러리
     
    → 이 중에서 JUnit과 AssertJ를 가장 많이 사용한다!
     

    ✅ JUnit이란?

    📋
    JUnit은 자바 언어를 위한 단위 테스트 프레임워크이다. 단위 테스트란, 작성한 코드가 나의 의도에 맞게 동작하는 지 작은 단위로 검증하는 것을 말한다(이때 보통 단위는 하나의 메소드를 의미한다).
     

    JUnit의 특징

    • @Test 어노테이션으로 메소드를 호출할 때마다 새로운 인스턴스를 생성한다.
    • 예상 결과를 검증하는 Assertion 메소드를 제공한다.
    • 사용법이 단순하다.
    • 자동으로 실행하고, 자체적으로 결과를 확인해 피드백을 제공한다.
     

    코드 예시

    @Test @DisplayName("상품 1개 등록하기 - TestRestTemplate 기반") void createProduct() { // given Long adminId = 1L; String name = "보조배터리"; Long price = 10000L; String category = "전자기기"; String thumbnailUrl = "http://abc.com"; ProductRequestMvc productRequestMvc = ProductRequestMvc.builder() .adminId(adminId) .name(name) .price(price) .category(category) .thumbnailUrl(thumbnailUrl) .build(); String url = "http://localhost:" + port + "/mvc/product/create"; // API url 주소 // when ResponseEntity<ProductResponseMvc> responseEntity = testRestTemplate.postForEntity(url, productRequestMvc, ProductResponseMvc.class); // then assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); ProductEntityMvc savedProduct = productServiceMvc.findById(responseEntity.getBody().getId()); Assertions.assertEquals(savedProduct.getAdminId(), adminId); Assertions.assertEquals(savedProduct.getName(), name); Assertions.assertEquals(savedProduct.getPrice(), price); Assertions.assertEquals(savedProduct.getCategory(), category); Assertions.assertEquals(savedProduct.getThumbnailUrl(), thumbnailUrl); }
     

    Given-When-Then Pattern

    코드를 자세히 살펴보았다면, given, when, then이라 주석처리 되어 있는 부분을 발견했을 것이다. given, when, then이 무엇일까? 이것은 테스트 코드를 작성할 때 흔히 사용하는 패턴이다. 테스트 진행 프로세스를 3가지로 나누어 각각에 맞는 작업을 수행하는 것이다.
    • given: 테스트 하기 위해 기본적으로 세팅하는 절차이다.
    • when: 테스트를 하기 위한 조건을 지정한다.
    • then: 테스트 하기 위한 행위와 결과값이 우리가 예상하는대로 잘 수행되는지 검증한다.
     
    이렇게 3가지 부분으로 나누어 테스트를 하기 위한 목적이 무엇인지 명확히 할 수 있다. 위 예시 코드에서 각각 수행하는 역할은 아래와 같다.
     
    • given
      • 상품 객체를 하나 생성한다.
    • when
      • testRestTemplate을 통해 상품 등록 API를 실행한다.
    • then
      • 상품이 잘 저장되었는지 서비스를 통해 가져와서 속성을 비교하며 확인한다.
      • Assertions.assertEquals(savedProduct.getAdminId(), adminId);에서 savedProduct.getAdminId()는 검증하고 싶은 값을 의미하고, adminId는 실제 비교할 값을 의미한다.
     
    위와 같은 상품을 등록하는 간단한 코드를 JUnit을 통해 작성할 수 있다.
     

    ✅ AssertJ로 검증문 수정하기

    AssertJ는 JUnit과 함께 사용하여 검증문의 가독성을 높여주는 라이브러리이다. 위 테스트 코드의 Assertions를 통한 검증문은 기댓값과 실제 비교값을 명시하지 않으므로 비교 대상이 헷갈릴 수 있다.
    이를 해결하기 위해 AssertJ를 사용하여 코드를 아래와 같이 수정할 수 있다.
     
    Assertions.assertEquals(savedProduct.getAdminId(), adminId);
    Assertions 사용 코드
     
    assertThat(savedProduct.getAdminId()).isEqualTo(adminId);
    AssertJ 사용 코드
     
    위처럼 assertThat()을 사용하면, 검증할 값과 실제 비교 대상을 명확하게 표현할 수 있다. 따라서, 수정한 최종 코드는 아래와 같다.
     
    @Test @DisplayName("상품 1개 등록 - TestRestTemplate 기반") void createProduct() { // given Long adminId = 1L; String name = "보조배터리"; Long price = 10000L; String category = "전자기기"; String thumbnailUrl = "http://abc.com"; ProductRequestMvc productRequestMvc = ProductRequestMvc.builder() .adminId(adminId) .name(name) .price(price) .category(category) .thumbnailUrl(thumbnailUrl) .build(); String url = "http://localhost:" + port + "/mvc/product/create"; // when ResponseEntity<ProductResponseMvc> responseEntity = testRestTemplate.postForEntity(url, productRequestMvc, ProductResponseMvc.class); // then assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK); ProductEntityMvc savedProduct = productServiceMvc.findById(responseEntity.getBody().getId()); assertThat(savedProduct.getAdminId()).isEqualTo(adminId); assertThat(savedProduct.getName()).isEqualTo(name); assertThat(savedProduct.getPrice()).isEqualTo(price); assertThat(savedProduct.getCategory()).isEqualTo(category); assertThat(savedProduct.getThumbnailUrl()).isEqualTo(thumbnailUrl); }
     
    위에서 사용한 isEqualTo()는 값이 같은지 검증하는 코드이다. 이 외에도 아래와 같이 여러가지 다양한 검증 메소드가 존재한다.
     
    메소드
    설명
    isEqualTo(X)
    X 값과 같은지 검증
    isNotEqualTo(X)
    X 값과 다른지 검증
    contains(X)
    X 값을 포함하는지 검증
    doesNotContain(X)
    X 값을 포함하지 않는지 검증
    startsWith(X)
    접두사가 X인지 검증
    endsWith(X)
    접미사가 X인지 검증
    isEmpty(X)
    비어있는 값인지 검증
    isNotEmpty()
    비어있지 않은 값인지 검증
    isPositive()
    양수인지 검증
    isNegative()
    음수인지 검증
    isGreaterThan(N)
    N보다 큰 값인지 검증
    isLessThan(N)
    N보다 작은 값인지 검증
     
    추후에 Mock, TestRestTemplate 등에 대해서도 알아보자!
     
    Share article
    Contents
    ✅ 들어가기 전에✅ JUnit이란?JUnit의 특징코드 예시Given-When-Then Pattern✅ AssertJ로 검증문 수정하기

    soultree

    RSS·Powered by Inblog