몬그로이

TIL_039 본문

TIL

TIL_039

Mon Groy 2024. 6. 15. 00:03

 

단위 테스트 FIRST 규칙

단위테스트 FIRST 규칙

  • Fast : 테스트는 빠르게 동작하고 자주 가동 해야한다.
  • Independent : 각각의 테스트는 독립적어이야 하며, 서로에 대한 의존성은 없어야 한다.
  • Repeatable : 어느 환경에서도 반복이 가능해야 한다.
  • Self-Validating : 테스트는 성공 또는 실패 값으로 결과를 내어 자체적으로 검증 되어야 한다.
  • Timely : 테스트는 테스트 하려는 실제 코드를 구현하기 직전에 구현 해야한다. (테스트 주도 개발 , TDD)

TDD (Test-Driven Development)

TDD는 소프트웨어 개발 방법론으로, 아래와 같은 단계를 따릅니다:

  1. 테스트 작성: 먼저, 구현하려는 기능에 대한 테스트 코드를 작성합니다. 이때, 아직 실제 기능은 구현되지 않았기 때문에 테스트는 실패할 것입니다.
  2. 테스트 실행: 작성한 테스트를 실행하여, 테스트가 실패하는 것을 확인합니다. 이는 테스트가 올바르게 작성되었음을 의미합니다.
  3. 코드 작성: 테스트를 통과하게 할 최소한의 실제 코드를 작성합니다.
  4. 테스트 실행: 다시 테스트를 실행하여, 작성한 코드가 테스트를 통과하는지 확인합니다.
  5. 리팩토링: 테스트를 통과한다면, 코드를 리팩토링하여 개선합니다. 리팩토링 후에도 테스트는 통과해야 합니다.

Timely 규칙의 장점

  • 버그 감소: 테스트를 먼저 작성함으로써, 코드 작성 시 발생할 수 있는 버그를 미리 발견할 수 있습니다.
  • 설계 개선: 테스트를 먼저 작성하면, 코드의 인터페이스와 설계가 더 깔끔하고 테스트 가능하게 됩니다.
  • 문서화: 테스트 코드는 코드의 사용 방법과 기대되는 동작을 문서화하는 효과가 있습니다.
  • 안정성: 리팩토링이나 기능 추가 시 기존 기능이 정상 동작하는지를 확인할 수 있습니다.

과제 설명에 참고하라고 들어있는 링크가 정말 많아서 보는데 한참 걸리기에 일단 시작하기로 했다

쉬운 것부터 해보려고 service 메서드 단위 테스트를 골랐는데,

Todo 등록 후 반영이 잘 되었는지 확인하는 test 코드를 작성하는 곳에서 벌써부터 막힌다

 

짧게 작성되었고 뭔가 더 필요 없다고 여기고 있었는데 실행이 되지 않아 한 튜터님의 도움을 받았다

그 후 열심히 흐름을 분석했고, 다른 튜터님께 내가 생각한 흐름과 설정 이유를 확인 받았다

두 번째 테스트 코드를 작성했는데, UnnecessaryException 이라고 자꾸 나와서 또 다른 튜터님을 찾아갔다

findByUserAndTodoId

는 repository 의 메서드이고, 이게 필수인데 이상하게 이걸 지워야만 테스트가 성공으로 떴다

디버그 모드로 찾아봐 주셨고, 튜터님은 판단이 끝나신 모양

내가 thenThrow 와 thenReturn 등에 명확한 설명을 하지 못하자, 이걸 찾아보면 풀 수 있을 거라고 힌트를 주셨다

 

OngoingStubbing 메서드로 when 에 넣은 메서드의 리턴값을 정의해 주는 메서드라고 한다

when({스터빙할 메서드}).{ongoinStubbing 메서드};

예를 들면

when(userRepository.getUser()).thenReturn(user); 같은 식이다

종류는 thenReturn, thenThrow, thenAnswer, thenCallRealMethod 로

각각 메서드 호출 후

어떤 객체를 리턴할 건지, 어떤 Exception을 throw할 건지, 어떤 작업을 할 건지(cutom설정), 실제 메서드 호출

 

비슷한 것으로 Stubber 메서드도 있다

{Stubber 메서드}.when({스터빙할 클래스}).{스터빙할 메서드}

doReturn, doThrow, doAnswer, doNothing, doCallRealMethod

호출 후 각각

어떤 행동을 할 건지, 어떤 Exception을 throw 할 건지, 할 작업을 (custom) 할 건지, 어떤 행동도 하지 않게할 것, 실제 메서드 호출

 

힌트를 발판삼아 테스트 코드를 완성했다


Entity 테스트 코드 (Domain Test) 를 연달아 시도하게 되었는데

잘 모르겠어서 구글링을 했더니 @DataJpaTest @SpringBootTest 외 1종 이 보였고

차이가 뭔지 모르겠어서 많이 해맸다

 

@DataJpaTest 는 DB를 직접 통하므로 @Mock 을 사용할 필요가 없고

@SpringBootTest 는 @Mock 사용이 가능했다

기억에 남기고자 두 가지 모두 테스트 코드를 작성했다

 

Assertions 나 assertThat 이 제대로 import 되지 않아서 뒤적거리다가

단언문이라는 게 있다는 걸 알게되었다

assertThat(A).isNotNull();

이 바로 그것인데, 이는 코드 작성자가 이렇다고 단정짓는 것으로

만약 실제로 충족되지 않는 것이었다면 예외가 발생하고 끝난다고 한다

 

알게된 김에 마침 적용 못하고 있던 UserService 테스트 클래스에

CreatedAt 이 null 인지 아닌지 확인하도록 집어 넣었다

 


@Mock

  • 단위 테스트에서 사용된다.
  • Mock 객체를 직접 생성하여 사용하므로, 스프링 컨텍스트와 관련이 없다.

@MockBean

  • 통합 테스트를 수행할 때 사용된다.
  • Mock 객체를 생성하고, 스프링 컨텍스트에 등록을 한다.

 

'TIL' 카테고리의 다른 글

TIL_041, 042  (1) 2024.06.18
TIL_040  (1) 2024.06.16
TIL_037  (0) 2024.06.12
TIL_35, 36  (0) 2024.06.11
TIL_034  (0) 2024.06.07