[박우빈, Practical Testing #6]Mock을 마주하는 자세

dev_lee·2024년 12월 2일
post-thumbnail

Stubbing

Stubbing이란?

실제 동작을 수행하지 않고 특정 입력에 대해 원하는 출력을 정의하여 단순히 테스트에서 필요한 값을 반환하도록 동작을 정의하는 것이다.

Mockito.when(mailSendClient.sendEmail(any(String.class), any(String.class), any(String.class), any(String.class)))
                .thenReturn(true);
  • when()
    Stubbing을 설정할 때 사용하는 메서드이며, 어떤 메서드 호출이 일어날 때 특정 동작을 정의하고 싶을 때 사용한다.

  • thenReturn()
    Stubbing의 핵심 부분이며, 특정 메서드가 호출되었을 때 반환될 값을 지정한다.

  • any()
    어떤 타입의 값이라도 허용한다는 뜻이며, 특정 값에 제한을 두지 않고, 호출되는 메서드가 어떤 값을 입력으로 받아도 설정된 동작이 실행되게 한다.

❗️실제 mailSendClient.sendEmail()는 호출되지 않는다.
Mockito가 메서드 호출을 가로채서 호출 자체를 기록하거나, 원하는 동작(Stubbing)을 설정할 수 있도록 하기 때문이다. 즉, 실제 메서드의 구현 코드는 실행되지 않고, 대신 Mockito가 해당 호출을 처리한다.

Stubbing 사용의 이점

  • 외부 의존성 제거
    실제 메서드의 구현이 동작하지 않으므로, 외부 시스템(데이터베이스, API 호출 등)에 의존하지 않는다.

  • 결과 제어
    특정한 테스트 시나리오를 설정하기 위해 원하는 값을 반환할 수 있다.

  • 빠르고 독립적인 테스트 가능
    외부 리소스를 호출하지 않기 때문에 테스트 속도가 빠르고 안정적이다.

Test Double

테스트 더블의 5가지 종류

https://martinfowler.com/articles/mocksArentStubs.html

  • Dummy : 아무 것도 하지 않는 깡통 객체
  • Fake : 단순한 형태로 동일한 가능은 수행하나, 프로덕션에서 쓰기에는 부족한 객체 (ex. FakeRepository)
  • Stub : 테스트에서 요청한 것에 대해 미리 준비한 결과를 제공하는 객체. 그 외에는 응답하지 않는다.
  • Spy : Stub이면서 호출된 내용을 기록하여 보여줄 수 있는 객체. 일부는 실제 객체처럼 동작시키고 일부만 Stubbing 할 수 있다.
  • Mock : 행위에 대한 기대를 명세하고, 그에 따라 동작하도록 만들어진 객체

    Stub vs Mock
    검증하려는 목적이 다르다.
    Stub : 상태 검증 (State Verification)
    Mock : 행위 검증 (Behavior Verification)

순수 Mockito로 검증해보기

순수 Mockito 어노테이션

@ExtendWith(MockitoExtension.class)
Mockito와 JUnit 5(Jupiter) 테스트를 통합하기 위해 사용되는 어노테이션이다. 테스트 클래스의 Mockito 기능을 활성화하고, Mock 객체의 초기화 및 관리 작업을 자동으로 처리하므로 순수 Mockito를 사용할 때 클래스 선언 윗 부분에 작성해준다.

@Mock

Mock 객체를 생성한다. Mock 객체는 가짜 객체로, 실제 객체의 동작을 대체하며 메서드 호출 시 미리 정의된 동작(Stubbing)을 수행한다. 주로 단위 테스트에서 사용.

  • Mock 객체 Stubbing
when(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
	.thenReturn(true);

@Spy

Spy 객체를 생성한다. Spy 객체는 실제 객체를 감싸는 형태로 동작하며, 필요에 따라 특정 메서드만 Stubbing할 수 있다.
일부 메서드는 실제로 호출되고, 일부는 Stubbing된 동작을 수행한다.

  • Spy 객체 Stubbing
doReturn(true)
	.when(mailSendClient)
    .sendEmail(anyString(), anyString(), anyString(), anyString());

@InjectMocks

테스트 대상 객체를 생성하고, 필요한 의존성을 @Mock 또는 @Spy 객체로 자동으로 주입한다. 의존성이 많은 객체를 테스트할 때 편리하다.

⭐️ @Mock, @Spy와 @InjectMocks
@Mock, @Spy는 테스트 대상 객체(@InjectMocks)의 의존성을 대체하는 데 사용한다.

참고) Spring Boot 어노테이션

@MockBean

Mock 객체를 생성하고, Spring의 ApplicationContext에 주입한다.
Spring 컨텍스트에 등록된 Bean을 Mock 객체로 대체하며, 주로 통합 테스트에서 특정 Bean을 Mocking해야 할 때 사용한다.

@SpyBean

Spy 객체를 생성하고, Spring의 ApplicationContext에 주입한다. 원래 Bean의 동작을 수행하면서 일부 메서드만 Mocking 가능하다.

BDDMockito

BDD 스타일로 테스트를 작성할 수 있도록 지원하는 Mockito의 확장 기능이다.

BDDMockito.given(mailSendClient.sendEmail(anyString(), anyString(), anyString(), anyString()))
                .willReturn(true);
  • given()
    기존의 when() 메서드에 해당하며, 어떤 조건에서 특정 동작을 수행해야 하는지 정의한다.
  • willReturn()
    기존의 thenReturn() 메서드에 해당하며, Stubbing의 결과 반환값을 설정한다.

현재 강의에서 BDD 스타일로 테스트 코드를 작성하고 있으므로 Mockito.when()절 대신 BDDMockito.given()절을 사용하기


출처 - 박우빈, Practical Testing: 실용적인 테스트 가이드
이 블로그에 포함된 모든 코드와 이미지는 원작자이신 박우빈 강사님의 저작권에 귀속됩니다.

0개의 댓글