관리 메뉴

miinsun

[Spring] Spring Boot를 이용한 단위·통합 테스트 본문

WebApp/Spring

[Spring] Spring Boot를 이용한 단위·통합 테스트

miinsun 2022. 1. 13. 18:43

1. 단위 테스트

단위 테스트란?
프로그램을 작은 단위로 쪼개서 각 단위가 정확하게 동작하는지 검사하고 이를 통해 문제 발생 시 정확하게 어느 부분이 잘못되었는지를 재빨리 확인할 수 있게 해준다.

 

  • JUnit을 이용한 단위 테스트
    • JUnit이란 자바 프로그래밍 언어용 단위 테스트 프레임워크이다.
    • ex)
      @DisplayName("자동차가 전진한다")
      @Test
      public void moveCar() {
          // given
          Car car = new Car("dani");
      
          // when
          car.move(4);
      
          // then
          assertThat(car.getPosition()).isEqualTo(1);
      }
      
      @DisplayName("자동차가 멈춘다")
      @Test
      public void stopCar() {
          // given
          Car car = new Car("dani");
      
          // when
          car.move(3);
      
          // then
          assertThat(car.getPosition()).isEqualTo(0);
      }​
  • Edge 케이스를 고려한 단위 테스트
    • Edge case란?
      • Edge case는 경계 조건으로 알고리즘이 처리하는 데이터의 값이 알고리즘의 특성에 따른 일정한 범위를 넘을 경우에 발생하는 문제를 가리킨다.
      • Edge case는 알고리즘의 특성에 따라 개발자가 면밀히 검토하여 예상할 수 있는 문제다. 이런 문제는 디버그가 쉽기도 하고 테스트를 통해 미리 방지하기도 쉽다.
      • Boundary case라고도 한다.
    • Edge case 처리 방법
      • Edge case를 발견 후 처리할 때는 개발자가 독단적인 방향으로 결정하는 것보다 관련 담당자들과 협의 진행 후 결정하는 것이 좋다.
    • TDD(Test-Driven Development)
      • 설계 → 개발 → 테스트(설계 수정)의 과정을 설계 → 테스트(설계 수정) → 개발로 변경 
  • Mock object 직접 구현을 통한 단위 테스트
    • Mock object란?
      • 실제 객체를 만들어 사용하기에 시간, 비용 등의 Cost가 높거나 혹은 객체 서로간의 의존성이 강해 구현하기 힘들 경우 가짜 객체를 만들어 사용하는 방법이다.
    • Mockito framework란
      • Mock 객체를 쉽게 만들 수 있는 방법을 제공하는 framework이다.
      •  Mockito Annotation
        • @ExtendWith(MockitoExtension.class): 테스트 클래스가 Mockito를 사용함을 의미
        • @Mock : mock 객체를 만들어 반환
        • @MockBean : ApplicationContext에 mock객체를 추가
        • @InjectMocks : @Mock 객체를 자신의 멤버 클래스와 일치해 주입
      • ex)
        @ExtendWith(MockitoExtension.class)
        class UserServiceTest {
            @Mock
            UserRepository userRepository;
            @InjectMocks
            UserService userService;
        }​
         
      • 공식 사이트 https://site.mockito.org/

 

2. 통합 테스트

통합 테스트란?

단위 테스트 이후, 각 모듈들의 상호 작용이 제대로 이루어지는지 검증하는 테스트로써 모듈을 통합하는 과정에서 발생할 수 있는 오류를 찾는 테스트이다

 

  • 통합 테스트의 유형
    • 하향식(Top-Down)
      • 가장 상부의 모듈부터 통합하며 테스트를 순차적으로 진행하는 방식이다.
      • 결함 격리가 쉬우며, 설계상의 결함을 빨리 발결할 수 있음
      • 수정이 어려운 중요한 결함을 하부 구조에서 발견 될 수 있음
    • 상향식(Bottom-Up)
      • 최하위 모듈을 통합 후, 상부의 모듈을 순차적으로 추가 테스트
      • 결함 격리가 쉬우며, 하위 모듈을 충분히 테스트 수행
      • 수정이 어려운 중요한 결함(설계상 결함)을 상부 구조에서 발견 될 수 있음
    • 단위 테스트 VS 통합 테스트
      • 단위 테스트는 하나의 모듈이나 클래스에 대한 세밀한 부분까지 테스트가 가능하지만, 모듈 간의 상호 작용 검증을 하지 못한다.
      • 통합 테스트는 두 개 이상의 모듈이 연결된 상태를 테스트 함으로 모듈 간의 연결에서 발생하는 에러를 검증 할 수 있다.
      • +) 블랙박스 테스팅 : E2E(End to End Test) 테스트는 실제 사용자의 실행 환경과 거의 동일한 환경에서 테스트를 진행한다.
  • 스프링 부트를 이용한 통합 테스트
    • 통합 테스트는 여러 단위의 테스트들을 통합하여 수행한다. Controller → Service → Repository
    • @SpringBootTest
      • 스프링 부트가 제공하는 테스트 어노테이션
      • 테스트 수행 시 스프링이 동작하게 해준다.
      • 특이점 
        • Spring IoC 사용 가능
        • Repository를 이용한 DB CRUD 사용 가능
        • E2E 테스트 사용 가능
          • Client 요청 → Controller → Service → Repository → Client 응답
        • 순서를 지정할 수 있다.
          • @Order(1), @Order(2), ...
    • ex)
      @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
      @TestInstance(TestInstance.Lifecycle.PER_CLASS)
      @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
      class IntegrationTest{
      	@Autowired
          StudentService studentService;
          
          int id;
          int department;
          String name = "none";
          
          @Test
          @Order(1)
          @DisplayName("학생 정보 등록")
          void test1(){
          	//given
              int id = 15;
              int department = 5;
              String name = "윤OO";
              StudentRequestDto requestDto = new StudentRequestDto(
              	id,
                  department,
                  name
              );
              //when
              Student student = studentService.enrollStudent(requestDto);
              //then
              assertNotNull(student.getId());
              assertEquals(id, student.getId());
              assertEquals(department, student.getDepartment());
              assertEquals(name, student.getName());
              }
          }
          
          @Test
          @Order(2)
          @DisplayName("학생 정보 변경")
          void test2(){
          	...
          }
          
          @Test
          @Order(3)
          @DisplayName("학생 정보 조회")
          void test3(){
          	...
          }
      }​

 

3. 테스트 별 장/단점

  • 클라이언트 코드에서 호출
    • 장점) 실제 서비스를 사용하게 될 고객의 입장에서 기능을 검증 할 수 있다.
    • 단점) 클라이언트 코드(HTML, CSS, JS) 가 작성 돼 있어야만 기능 검증이 가능하다.
  • API 호출 앱 사용
    • 장점) UI 없이 서버의 API를 솝쉽게 검증 가능하다.
    • 단점) 여러개의 API를 한번에 검증하기 어렵다.
  • 스프링의 테스트 프레임워크 사용
    • 장점)
      • UI 없이 서버의 API를 솝쉽게 검증 가능하다.
      • 여러개의 API를 한번에 검증 가능하다.
      • 테스트 코드를 소스 코드와 함께 관리 할 수 있다.
      • 코드 수정 후 바로 테스트 가능하다.
      • Git을 이용해 다른 개발자들과 테스트 코드 공유 가능하다.
    • 단점)
      • 테스트 프레임워크에 대한 추가학습이 필요하다.
      • 테스트 코드 작성에 시간이 소요된다.

 

참고 )

 

통합테스트(Integration Test)

통합테스트는 모듈을 통합(Integrate)하는 단계에서 수행하는 테스트이다. 단위 테스트를 우선 수행하여 모듈들이 각각 정상적으로 작동이 되는 것을 확인했다면 이제 이 모듈들을 연동하여 테스

needjarvis.tistory.com

 

Comments