GitHub

https://github.com/Choidongjun0830

Spring

[원티드 백엔드 챌린지 11월] 테스트 코드와 API 문서화 자동화

gogi masidda 2024. 11. 22. 15:36

ArchUnit

  • 아키텍처에 대해 정리한 문서 없이도 서술적인 메서드명을 통해서 아키텍처 구조에 대해서 이해할 수 있고, 아키텍처의 규칙 또한 쉽게 정의할 수 있으며 더불어 검사 기능까지 제공해주는 테스트 툴 라이브러리
  • 프로젝트의 아키텍처 구조를 Test Code로 강제화하는 방법론 
  • 적용 방법
    • 1. 의존성 추가
      • testImplementation("com.tngtech.archunit:archunit-junit5:1.2.1")
    • 2. 아키텍처에 대한 규칙 정의; 시나리오 작성
      • 예시
        • Controller 계층에서는 Service 계층만 참조 가능
        • presentation.web 패키지의 클래스는 port.in 클래스에만 의존해야 한다.
        • presentation.web 패키지의 하위 클래스는 @Controller나 @RestController를 선언해야 하고, 이름은 Controller로 끝나야 한다.
      • ArchUnit에는 not 연산자가 없어서 '~는 ~이다' 라고만 시나리오를 써야 한다. 
    • 3. 그 규칙에 대한 검증 코드 작성 
      • 예시 - Controller 계층에서는 Service 계층만 참조 가능하다. 
@AnalyzeClasses(packages= "com.wanted.clone.oneport")
public class Arch2Tests {
	@ArchTest
    public static final ArchRule controllerRuleTest = classes().that().resizeInAPackage("..presentation.web")
    	.should().beAnnotatedWith(RestController.class)
        .orShould().beAnnotatedWith(Controller.class)
        .orShould().haveSimpleNameContaining("Controller");
}
    • 4. 검증 코드 실행; 유효성 검사 

Test Doubles

  • 대역 배우. 테스트 Dummy 
  • 단위 테스트를 진행하는데 생성하기 까다롭거나 아직 생성되지 않은 클래스를 직접 생성해서 테스트하지 않고, 이를 대신해 테스트를 진행할 수 있도록 만들어진 객체 
  • Stub
    • 테스트 중에 특정 클래스의 메서드 호출에 대해 미리 준비된 답변을 제공하는 대역 클래스
    • 실제 객체처럼 동작하는 클래스를 구현하지만, 테스트에 필요한 결과만 반환하도록 구현 
    • 어떤 입력에 대해 어떤 출력이 나오게 구현 
  • Mock
    • 실제 객체의 동작을 모방하는 객체
    • 시나리오에 기반해 호출된 메서드에 대해 기대 결과를 명세하고, 테스트 실행 후, 미리 정의 해놓은 내용에 따라 동작(or 호출)했는지 검증하는 용도로 사용 
  • 사용 이유
    • 주요 관심사에 집중하기 위함 
  • Mockito를 이용하여 Stub/Mock/Spy 객체를 쉽게 생성, 관리, 검증 가능 
    • 사용법
      • 사용 흐름 
        • 1. 의존성 추가
        • 2. 테스트 클래스에 JUnit과 연동하기 위한 ExtendWith 선언
        • 3. 생성하기 어렵거나 곤란한 객체는 Mock 객체로 선언
        • 4. 테스트 시나리오 기반으로 검증 코드 작성
        • 5. 검증 
      • 사용법
        • @Mock
          • 어노테이션이 붙은 객체를 Mock 객체로 생성해주는 어노테이션 
          • 생성 후 의존성 주입이 필요 
        • @MockBean 
          • Spring Context에 Mock 객체를 등록하고, 테스트 코드에서 @Autowired가 동작할 때 Mock이 자동 주입될 수 있도록 Spring Bean으로 등록해주는 어노테이션 
        • @InjectMocks
          • 테스트 코드에 사용되는 클래스 중 의존성 주입이 필요한 클래스가 Bean으로 등록된 Mock 객체를 찾아서 의존성을 주입하고 초기화할 수 있도록 함 
          • @Mock으로 Mock 객체를 생성하고 @InjectMocks로 의존성 주입이 필요한 객체를 만들면 알아서 @Mock 객체를 찾아 주입 
      • Given - When - Then
        • 어떤 특정 환경이 주어졌을 때(Given), 어떤 행위를 하였고(When), 그 결과(Then)이 기대한 결과와 동일한지. 

SpringBootTest

  • SpringBoot의 Context 영역을 이용하여 테스트할 수 있도록 해주는 어노테이션
    • SpringBoot의 Context 영역을 이용한다는 것은 Bean으로 등록된 객체를 사용한다는 의미 
      • 모든 Bean을 띄워야 해서 시간이 오래 걸릴수도
  • 언제 사용?
    • 통합 테스트 용도로 제공하는 가장 기본적인 Test 어노테이션으로 단위 테스트 및 구현이 완료되었을 때, 요청부터 응답까지 의도대로 동작하는지 최종적으로 확인할 때 사용 
  • 파라미터
    • properties
      • 임시 설정 값을 정의 및 선언 가능
      • 같은 프로파일에서 다른 설정 값을 사용할 때 사용
      • resources/application-test.yaml 이나 application.yaml에 test profile을 사용하여 설정 값을 사용하는 방법도 있다. 
    • classes
      • classes 속성에 선언한 클래스만 초기화 후, Bean으로 등록
      • SpringBootTest는 프로젝트 패키지에 등록된 Bean을 모두 생성해서 애플리케이션의 규모가 클수록 테스트 소요 시간이 길어진다. classes를 사용하여 특정한 클래스만 선택할 수 있도록 하는 것이다.
      • @Configuration으로 지정한 Bean도 등록할 수 있다. 
    • webEnvironment
      • SpringBoot에 내장되어 있는 Tomcat 서버의 설정을 할 수 있는 속성
        • Options
          • WebEnvironment.MOCK
            • 디폴트 설정으로 내장 톰캣이 실행되지 않는다.
          • WebEnvironment.RANDOM_PORT
            • 서비스 포트가 랜덤으로 지정되고 상용 애플리케이션에서 구동되는 것처럼 내장 Tomcat이 실행된다.
          • WebEnvironment.DEFINED_PORT
            • 지정된 포트로 내장 Tomcat이 실행된다. 
    • @AutoConfigureTestDatabase
      • 테스트 시, 사용될 DB에 대한 구성 및 설정할 때 사용되는 어노테이션
      • 내장형 Test DB로 선택 및 설정할 수 있다. 또는 환경에 맞게 구축된 실서비스 DB를 선택할 수도 있다. 
    • @DataJpaTest
      • 영속성에 대한 테스트만 할 때 사용
      • 영속성 컨텍스트까지만 데이터가 전달되고 flush()를 하지 않아서 Log 상에 쿼리 관련 로그가 보이지 않게 된다. 
  • 배포 전에 미리 테스트 코드 가능한 작성하기 

API 문서화

  • 자동화 도구 적용
    • Spring Rest Docs
      • WEB UI를 제공하며 비즈니스 코드에 문서화와 관련된 코드 추가가 필요 없다. 
      • Test Code 및 Test 통과가 필수 조건 
    • Swagger
      • WEB UI를 제공하며, 쉽고 빠르게 적용 가능
      • Controller에 비즈니스 코드가 아닌 API 문서 자동화를 위한 코드가 추가 되어야 함. 
      • Controller에 비즈니스 코드가 아닌 문서 관련 코드가 있는게 단점
728x90