Dev

일단 단위 테스트부터 테스트 코드 작성해보기

khjoon 2024. 12. 4. 22:20

테스트 코드 작성하는 이유

지금까지 테스트를 Swagger로 했는데 리팩토링 작업을 하면서 테스트 작업을 해야하는데 Swagger로 다시 테스트를 하기에는 너무 번거로운 작업이었고 테스트 코드를 작성하면서 기존에 발견하지 못했던 버그가 있으면 찾고자 작성하였습니다.

단위테스트 vs 통합테스트

단위 테스트는 개별 구성 요소의 기능을 개별적으로 확인하고 통합 테스트는 여러 구성 요소가 올바르게 함께 작동하는지 확인합니다.
단위 테스트는 개발하면서 같이 작성해야 했는데 업보라고 생각하고 단위테스트부터 작성하였습니다.

JUnit5와 Mockito

JUnit 5와 Mockito는 Java 개발자가 단위 테스트를 작성하고 모의 객체(Mock Objects)를 사용하여 테스트하는 데에 널리 사용되는 라이브러리입니다.
각각 JUnit 5는 테스트 프레임워크이고, Mockito는 모의 객체를 생성하고 테스트할 때 사용됩니다.
JUnit 5를 사용하여 테스트 케이스를 정의하고 Mockito를 사용하여 외부 의존성을 가지는 컴포넌트를 가상화하여 테스트를 수행할 수 있습니다.

테스트 파일 생성

  1. 테스트 하고자 하는 부분에서 cmd+n으로 JUnit Test 파일을 생성했습니다.

@Mock

  • 테스트할 때 사용할 수 있는 가짜 객체를 생성해줍니다.
  • 스터빙 작업을 할 때 필요합니다.(스터빙이란 임의의 값을 직접 넣어주는 작업)
  • @Mock annotation으로 추가할 수 있습니다.
    @Mock을 사용하려면 @ExtendWith(MockitoExtension.class)를 추가해줘야 합니다.

@InjectMocks

  • mock 객체를 해당 클래스로 자동으로 주입해주는 어노테이션입니다.

@BeforeEach

  • 테스트가 동작하기 전에 값을 미리 설정할 수 있습니다.

@Test

  • Test 코드를 작성해줍니다.
  • given-when-then 패턴을 이용했습니다.
  • given으로 return값을 설정하는 스터빙 작업을 했습니다.
  • assertJ를 이용해서 결과값을 비교했습니다.

Junit이 아니라 AsserJ를 사용한 이유는 method chaining 방식이 좀 더 직관적이라고 생각해서 사용했습니다.

@BeforeEach
public void setUp(){
    email = "test";
    password = "1234";
    request = new MemberRequestDTO.LoginDTO(email, password);

    member = Member.builder()
            .id(1L)
            .email(email)
            .build();

    encodedPassword = new BCryptPasswordEncoder().encode(password);
    memberPassword = MemberPassword.builder().build();
    memberPassword.setPassword(encodedPassword);

    accessToken = "accessToken";
    refresh = "refreshToken";
    LocalDateTime localDateTime = LocalDateTime.now();
    refreshToken = RefreshToken.builder()
                .token(refresh)
                .memberId(member.getId())
                .expireTime(localDateTime.plusHours(12))
                .build();
 }
@Test
@DisplayName("로그인 테스트")
void testLoginSuccess() {

     //give
     given(memberRepository.findByEmail(email)).willReturn(Optional.of(member));
     given(memberPasswordRepository.findByMember(member)).willReturn(memberPassword);
     given(encoder.matches(password, memberPassword.getPassword())).willReturn(true);
     given(redisService.saveLoginStatus(eq(member.getId()), any())).willReturn("accessToken");
        given(redisService.generateRefreshToken(email)).willReturn(refreshToken);

    //when
    MemberResponseDTO.LoginDTO result = memberService.login(request);

    //then
    assertThat(result).isNotNull();
    assertThat(accessToken).isEqualTo(result.getAccessToken());
    assertThat(accessToken).isEqualTo(result.getAccessToken());
    assertThat(refreshToken.getToken()).isEqualTo(result.getRefreshToken());
    }

@Verify

  • 검증(Verify) 는 스터빙한 메소드가 제대로 실행이 되는지 확인하는 기능입니다.
  • verify(T mock, VerificationMode mode)

단위 테스트 다 작성하고 통합 테스트 작성하기