Java

테스트 하기 쉬운 코드 && 테스트 범위와 종류

codingtori 2025. 10. 14. 11:30

테스트가 어려운 코드

●  하드 코딩된 경로 : 해당 경로에 파일이 반드시 위치해야함

●  의존 객체를 직접 생성

●  정적 메서드 사용

●  실행 시점에 따라 달라지는 결과

    ○ LocalDate.now() 혹은 Random 사용하는 코드

●  역할이 섞여 있는 코드

●  메서드 중간에 소켓 통신 코드 포함

    +) 소켓 통신이나 HTTP 통신의 경우 실제를 대체할 서버를 로컬에 띄워서 처리 가능 (서버 수준의 대역)

●  콘솔에서 입력을 받거나 결과를 콘솔에 출력

●  테스트 대상이 사용하는 의존 대상 클래스나 메서드가 final : 대역으로 대체하기 어려움

●  테스트 대상의 소스를 소유하고 있지 않아 수정이 어려움


테스트 가능한 설계

테스트가 어려운 주된 이유 = 의존하는 코드를 교체할 수 있는 수단이 없음

 

●  하드 코딩된 상수를 생성자나 파라미터로 받기

    - [어려운 점] 테스트 환경에 따라 경로를 다르게 줄 수 있는 수단 X

    - [해결 방법] 생성자나 세터를 이용해서 경로를 전달 받음 

      ex) 변수로 따로 분리하기, 메서드의 파라미터로 값을 전달받도록 하기

● 의존 대상을 주입 받기

    - [해결 방법] 생성자나 세터를 통해 의존 대상을 교체 (: 실제 구현 대신에 대역을 사용할 수 있음)

      * 만약 많은 레거시 코드에서 생성자 없는 버전 사용시 → 세터를 이용해서 의존대상 교체하도록 수정

      : 이렇게 함으로써 의존대상을 교체할 수 있도록 수정한 것임

 

테스트하고 싶은 코드를 분리하기

- 기능의 일부만 테스트하고 싶다면 해당 코드를 별도의 기능으로 분리하여 테스트 진행

(+) 일부 기능 자체를 대역으로 변경하고 싶다면 '의존 대상을 주입받기' 에서 설명한 것처럼 세터를 이용해서 의존 대상을 주입

 

● 시간이나 임의 값 생성 기능 분리하기

    - [어려운 점] 테스트 대상이 시간이나 임의 값을 사용하면 테스트 시점에 따라 테스트 결과가 달라짐

    - [해결 방법] 테스트 대상이 사용하는 시간이나 임의 값을 제공하는 기능을 별도 분리

    * 임의 값을 제공하는 라이브러리를 직접 사용하지 말고, 별도로 분리한 타입을 사용해서 대역으로 처리해야함

● 외부 라이브러리 대체 불가능한 경우 (정적 메서드 제공 시)

    - [어려운 점] 정적 메소드들은 상태를 가지지 않거나 전역 상태를 사용하고, mocking이 어려움.

    - [해결 방법] 외부 라이브러리를 직접 사용하지 말고 외부 라이브러리와 연동하기 위한 타입을 따로 만듬. 테스트 대상은 분리한                         타입을 사용하도록 함 (: 외부 연동이 필요한 기능을 쉽게 대역으로 대체 가능)


테스트 종류

테스트 범위에 따른 테스트 종류

  통합 테스트

    ○  개발 완료 후에 진행하는 최종 테스트

    ○  고객의 입장에서 요구한 기능을 올바르게 구현했는지 수행하는 테스트

    ○  소프트웨어의 코드를 직접 테스트함

    ○  대상 (web app의 경우) : 프레임워크, 라이브러리, 데이터베이스, 구현한 코드

●  인수 테스트

    ○  고객의 입장에서 요구한 기능을 올바르게 구현했는지 수행하는 테스트

    ○  요건을 완료했는지 정의하기 위해 작성한 테스트

●  기능 테스트

    ○  사용자 입장에서 시스템이 제공하는 기능이 올바르게 동작하는지 확인

    ○  시스템을 구동하고 사용하는데 필요한 모든 구성요소가 필요함

    ○  E2E 테스트에 속함

  E2E 테스트

    ○  모든 구성요소를 하나로 엮어서 진행 (사용자가 사용하는 웹 브라우저 부터 시작해서 외부서비스, DB에 이르기까지)

  단위 테스트

    ○  개별 코드나 컴포넌트가 기대한대로 동작하는 지 확인

    ○  한 클래스나 한 메서드와 같은 작은 범위 테스트

    ○  의존 대상의 경우 스텁이나 모의 객체를 이용해서 대역으로 대체

 

테스트를 자동화한다 == 코드로 작성한 테스트를 실행한다

 

* 정기적인 기능테스트 = 정상적인 경우와 몇 가지 특수한 상황만 테스트 범위로 잡음


WireMock = 서버 API를 스텁으로 대체

 

WireMock 사용방법

●  테스트 실행 전에 WireMockServer 시작. 실제 HTTP 서버 뜸

●  테스트에서 WireMockServer의 동작 기술

●  HTTP 연동을 수행하는 테스트 작성
●  테스트 실행 후에 WireMockServer를 중지

 

TestRestTemplate은 스프링 부트가 테스트 목적으로 제공. 내장 서버에 연결하는 RestTemplate.

 

 

 

 

 

 

 

 

 

 

'Java' 카테고리의 다른 글

TDD로 기능 추가해보기  (0) 2025.09.24
TDD 시작하기  (0) 2025.09.09
스프링 데이터 JPA  (2) 2025.08.17
나를 위한 클래스와 객체, 상속 부분 내용 정리  (0) 2023.05.16
끝말잇기 게임 만들기  (0) 2023.05.15