Spring boot - 테스트 코드 작성해보기

lin·2022년 12월 5일
0

앱 개발이 진행되면서 프론트에서 api 적용을 바로바로 해보며 진행을 원하셨기때문에, 코드 수정후 개발용 테스트 서버에 애플리케이션을 계속 올리면서 업무를 진행하게 되었다.

원하는 기능은 명확해서 그냥 뚝딱뚝딱 만들면 될 줄 알았는데, 꼭 서버에 올리고나면..
'어 안되는데...?' ㅠㅠ
ㅠㅠㅠ
ㅠㅠㅠㅠㅠㅠ

문제점은 다음과 같다.
1. 내가 기능을 제대로 이해못함.
2. API 코드를 수정하면서 연계되어있는 다른 API에서 에러가 나버림

테스트 코드가 이래서 필요하구나를 느낄 수 있는 교훈이였다.

TDD 방법론

Test Driven Development 의 약자로 테스트 주도 개발이다.
반복 테스트를 이용한 소프트웨어 방법론으로, 작은 단위의 테스트 케이스를 작성하고, 이를 통과하는 코드를 추가하는 단계를 반복하여 구현한다.

TDD 개발주기

  • RED : 실패하는 테스트 코드를 먼저 작성
  • Grenn : 테스트 코드를 성공시키기 위한 실제 코드를 작성
  • Yellow : 중복 코드 제거, 일반화 등의 리팩토링 수행

Why TDD?

일반의 개발 방식
요구사항 분석 -> 설계 -> 개발 -> 테스트 -> 배포

문제점
1. 소비자의 요구사항이 처음부터 명확하지 않을 수 있다.
2. 따라서 처음부터 완벽한 설계는 어렵다.
3. 소스코드의 품질이 저하될 수 있으며 자체 테스트 비용이 증가할 수 있다

TDD 개발 방식
테스트 코드를 먼저 작성한 후 실제 코드를 장석한다는 점
이를 통해 설계 단계에서 프로그래밍 목적을 미리 정의해야하고, 무엇을 테스트해야할 지 미리 정의해야만 한다.
테스트 코드를 작성하는 도중에 발생하는 예외 사항(버그, 수정사항)들은 테스트 케이스에 추가하고 설계를 개선한다. 이후 테스트가 통과된 코드만을 코드 개발 단계에서 실제 코드로 작성한다.

🔆 이러한 반복적인 단계가 진행되면서 자연스럽게 코드의 버그가 줄어들고, 소스코드는 간결해진다.

또한, 테스트 케이스 작성으로 인해 자연스럽게 설계가 개선됨으로 재설계 시간이 절감된다.

단위 테스트란?

프로그램을 작은 단위로 쪼개서 각 단위가 정확하게 동작하는지 검사하는 테스트

  • Junit이란?
    자바 프로그래밍 언어용 단위 테스트 프레임워크이다.
    어노테이션을 기반으로 테스트를 지원한다.
    Assert(단정문)을 통해서 테스트 케이스의 기대값에 대해 수행결과를 확인할 수 있다.

gradle 환경 설정

dependencies {
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

test {
    useJUnitPlatform()
}

Junit 어노테이션

  • Junit LifeCycle 어노테이션
  1. @Test : 테스트용 메소드를 표현하는 어노테이션
  2. @BeforeEach : 각 테스트 메소드가 시작되기 전에, 실행되어야 하는 메소드를 표현
  3. @AfterEach : 각 테스트 메소드가 종료된 후 실행되어야 하는 메소드를 표현
  4. @BeforeAll : 테스트 시작 전에 실행되어야 하는 메소드를 표현 (Static 처리)
  5. @AfterAll : 테스트 종료 후에 실행되어야 하는 메소드를 표현 (Static 처리)
  • Junit Main Annotation
    @SpringBootTest : 통합 테스트 용으로 SpringBootApplication의 하위 모든 Bean을 스캔하여 로드하고, Test용 Application Context를 만들어 Bean을 추가하고 MockBean을 찾아 교체한다.

@Disabled : 테스트를 실행하지 않게 설정하는 어노테이션

Assert 메소드

해당 메소드들을 통해 테스트가 정상적으로 수행되었는지 확인 가능

  1. assertEquals(a,b) : a와 b값이 동일한지 확인
  2. assertSame(a,b) : a와 b의 객체가 동일한지 확인
  3. assertNull(a) : a가 null인지 확인
  4. assertNotNull(a) : a가 null이 아닌지 확인
  5. assertTrue(a) : a가 true인지 확인
  6. assertFalse(a) : a가 false인지 확인
  7. assertThrows(a,b) : b 로직시 a 예외가 발생하는 지 확인
    ex ) 중복 에러 등등...
  8. assertThat :어떤 조건이 참인지 확인
/**
 * 게시물 삭제포함 단건 조회
 */
    @Test
    void 게시물_삭제포함_단건_조회() {
        log.info("###게시물_삭제포함_단건_조회");

        // given -> 비교 대상
        final Posts post = insertPost(1);

        String url = URL + "/" + post.getPostsId().getBoardNo() + "/" + post.getPostsId().getPostsNo();

        // when
        ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
                url,
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<PostsResponseDto>() {
                }
        );

        // then -> 내가 예상했던 값이랑 동일하게 처리가 되었는지 확인
        assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);

        PostsResponseDto dto = responseEntity.getBody();
        assertThat(dto).isNotNull();
        assertThat(dto.getBoardNo()).isEqualTo(post.getPostsId().getBoardNo());
        assertThat(dto.getPostsNo()).isEqualTo(post.getPostsId().getPostsNo());
        assertThat(dto.getPostsTitle()).isEqualTo(post.getPostsTitle());
        assertThat(dto.getPostsContent()).isEqualTo(post.getPostsContent());
        assertThat(dto.getPostsAnswerContent()).isEqualTo(post.getPostsAnswerContent());
        assertThat(dto.getAttachmentCode()).isEqualTo(post.getAttachmentCode());
        assertThat(dto.getReadCount()).isEqualTo(post.getReadCount() + 1);
        assertThat(dto.getNoticeAt()).isEqualTo(post.getNoticeAt());
    }

예제 프로젝트로 이해해보기

profile
BE

0개의 댓글