Mock: 진짜 객체와 비슷하게 동작하지만 프로그래머가 직접 그 객체의 행동을 관리하는 객체.

Mockito: Mock을 지원하는 프레임워크로, 객체를 쉽게 만들고 관리하고 검증할 수 있는 방법을 제공한다.

 

martinfowler.com/bliki/UnitTest.html

 

bliki: UnitTest

Unit Tests are focused on small parts of a code-base, defined in regular programming tools, and fast. There is disagreement on whether units should be solitary or sociable.

martinfowler.com

단위 테스트를 생각할 때, 클래스나 오브젝트, 또는 행동과 연관된 로직이라고 다양하게 생각할 수 있다.

나중에 테스트를 작성하게 되면 단위테스의 단위를 어떻게 정의할 것인가, Mock은 어느 범위에서 적용할 것인가 등을 함께 정하는 것이 좋다고 함

 

 

Mockito의 경우 스프링 부트를 사용하게 되면 spring-boot-starter-test의 의존성을 따라 자동으로 들어오게 된다.

만약 이 것을 사용하지 않은 경우엔 아래 2가지 의존성 추가가 필요하다.

  • mockito-junit-jupiter: junit test에서 mockito를 연동해서 사용할 수 있는 추가적인 확장 구현체를 제공하는 라이브러리
  • mockito-core: mockito가 제공하는 기본적인 기능들이 들어있는 라이브러리

 

Mock은 그럼 언제 사용하냐면?

외부 api등을 호출할 때, 어떻게 답이 오는지 가정 등을 하고 mock 객체로 만들어 이 것이 어떻게 동작하는지 테스트할 경우 등 사용한다.

또, 내가 만들고 있는 코드가 의존하는 클래스의 구현체는 없지만 인터페이스는 있고, 그 인터페이스 기반으로 코드를 작성할 때 그 것을 확인하기 위해 사용되기도 한다.

아래와 같은 두 가지 방법으로 Mock 객체를 만들 수 있다.

  • Mockito.mock: 생성자로 주입하는 방법
  • @Mock + @ExtendWith(MockitoExtension.class) - 함수 밖에 테스트 클래스의 필드로 주입할 수도 있고, 파라미터 전달도 가능하다

 

Mock 객체를 만든 후에는 Mock 객체의 행동을 조작해야한다. 이를 Stubbing이라고 한다.

모든 Mock 객체의 행동은 기본적으로 아래와 같이 행동한다.

  • 리턴 타입이 있다면 Null 리턴한다. (Optional 타입은 Optional.empty 리턴)
  • Primitive 타입은 프리미티브 기본 값을 따름
  • 콜렉션은 비어있는 콜렉션으로 만들어준다
  • Void 메소드는 예외를 던지지 않고 아무런 일도 발생하지 않는다

Mock 객체를 조작하기 위해서는 

  • Mockito.when(/*조건*/).thenReturn(/*객체*/): 조건에 해당한다면 무조건 어떠한 객체를 리턴하라
  • Mockito.when(/*조건*/).thenReturn(/*객체*/).thenThrow~~.thenReturn~~: 메소드가 여러 번 호출될 때 stubbing을 같은 매개변수로 호출 되더라도 호출되는 순서에 따라 다르게 mocking. 즉, 동일한 조건에 대해 다양한 객체/예외를 리턴하도록 설정해 둘 수 있다.
  • doThrow(/*Exception*/).when(/*조건*/): 조건에 해당한다면 어떠한 예외를 던져라

 

마지막으로 Mockito로 만든 Mock 객체가 어떻게 사용됐는지(객체에 어떤 일이 일어났는지) 확인하는 방법이다.

  • verify(memberService, times(1)).notify(study): 예를 들어 mock객체 memberService의 함수 notify가 1번만 호출되어야 한다
  • inOrder(memberService): 함수 호출에 대해 순서를 부여하고 싶은 경우

다른 여러가지 조건은 아래 공식문서를 확인하도록 하자

javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#verification_timeout

 

Mockito - mockito-core 3.7.7 javadoc

Latest version of org.mockito:mockito-core https://javadoc.io/doc/org.mockito/mockito-core Current version 3.7.7 https://javadoc.io/doc/org.mockito/mockito-core/3.7.7 package-list path (used for javadoc generation -link option) https://javadoc.io/doc/org.m

javadoc.io

 

 

Mockito에서는 별개로 BDD 스타일의 테스트를 할 수 있는 방법을 BddMockito 클래스를 통해 제공한다.

BDD (Behaviour-Driven Development): 애플리케이션이 어떻게 “행동”해야 하는지에 대한 공통된 이해를 구성하는 방법으로, TDD에서 창안했다.

BDD는 시나리오를 기반으로 테스트 케이스를 작성하며 함수 단위 테스트를 권장하지 않는다. 이 시나리오는 개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 레벨을 권장한다. 하나의 시나리오는 Given, When, Then 구조를 가지는 것을 기본 패턴으로 권장하며 각 절의 의미는 다음과 같다.

Feature : 테스트에 대상의 기능/책임을 명시한다
Scenario : 테스트 목적에 대한 상황을 설명한다
Given : 시나리오 진행에 필요한 값을 설정한다 - 어떤 상황이 주어졌을 때
When : 시나리오를 진행하는데 필요한 조건을 명시한다 - 무엇인가를 하면
Then : 시나리오를 완료했을 때 보장해야 하는 결과를 명시한다 - ~~할 것이다
위의 내용을 개발 측면에서 더 간략하게 정리하면 테스트 대상의 상태 변화를 테스트하는 것이다.
테스트 대상은 A 상태에서 출발하며(Given) 어떤 상태 변화를 가했을 때(When) 기대하는 상태로 완료되어야 한다. (Then)
또는 Side Effect가 전혀 없는 테스트 대상이라면 테스트 대상의 환경을 A 상태에 두고(Given) 어떤 행동을 요구했을 때(When) 기대하는 결과를 돌려받아야 한다. (Then)

 

+ Recent posts