Backend/Spring

[Spring boot] Mockito

나는 유찌 2020. 3. 8. 20:30

 

 

 

1. Mock Object(모의 객체)

 

Mockito를 알아보기 전 Mock에 대해서 알아야 할 필요가 있습니다!

Mock이란 가짜 객체를 의미합니다.

 

예를들어, 첨부파일을 업로드하고 삭제하는 기능을 테스트 한다고 가정하였을 때

html 화면까지 구성하고 데이터베이스에 연결하여 첨부파일을 넣고 삭제하고...

무언가 이상하면 코드를 수정하고 Spring이 실행될 때 까지 기다렸다가 화면에서 업로드하고 삭제를 반복해야하는 번거로움을 가지게 됩니다.

 

만일 테스트 코드를 작성하며 Mock 객체를 이용하게 된다면

화면 구성도 필요 없이 테스트 메소드 안에서 File이라는 객체를 가상으로 만들어 주어

테스트 코드에서 객체에 내용을 담아주고 테스트를 시행 할 수 있게 됩니다. 

(이해가 가시나요ㅎㅎ..)

 

 

 

2. Mockito

 

Mockito란 단위 테스트를 하기 위해 Mock을 만들어주는 Java Mocking Framework 입니다.

 

 

 

3. Mockito 사용

 

1) dependency 추가

 

해당 프로젝트의 pom.xml을 열고 'mockito-all' dependency를 추가합니다. (Junit 또한 추가 되어 있어야 합니다.)

 

<dependency>

<groupId>org.mockito</groupId>

<artifactId>mockito-all</artifactId>

<version>1.10.19</version>

<scope>test</scope>

</dependency>

 

 

2) Mock 객체 생성

 

Mock 객체 생성(=가짜 객체 생성)하는 방법은 두 가지가 있습니다.

(저의 경우 Model에 해당하는 Person 클래스를 만들어 이 클래스 파일로 테스트하여 캡쳐했습니다.)

 

1) annotation 이용

 

Mock 객체 생성1

첫번째 방법은 @Mock 이란 어노테이션을 이용하는 방법입니다.

@Before이란 어노테이션도 같이 들어있는 것을 볼 수 있습니다.

@Before은 테스트 코드를 시행하기 전 이 메소드를 실행하라는 의미를 가집니다.

 

Before 메소드 안에 들어있는 'MockitoAnnotations.initMocks(this)'라는 코드는

Mock 어노테이션이 선언된 변수들이 Mock 객체를 만들도록 하라는 의미를 가집니다.

 

저 코드가 없으면 Mock 객체가 만들어지지 않았다는 의미로 에러가 나게 됩니다.

 

 

2) mock() 이용

단위테스트를 진행할 메소드 안에서 목객체를 생성하는 방법입니다.

딱히 설명드릴게 여기는 없네요ㅎㅎ...

 

 

 

3) 테스트 코드 작성

 

위의 두가지 방법 중 하나로 Mock 객체를 생성했다면 본격적으로 테스트 코드를 작성해봅시다.

 

when()이란 특정 Mock 객체를 만들고 이 객체로부터 특정 조건을 지정하라는 의미입니다.

개인 정보가 포함 되어있어 색칠해 놓은 부분을 '유찌'라고 가정하고

 

when(p.getName()).thenReturn("유찌") 코드를 글로 풀어서 쓰자면

p.getName()이라는 메소드를 호출하면 '유찌'를 리턴하라는 의미입니다.

다음 코드는 위와 같이 p.getAge() 메소드를 호출하면 1을 리턴하라는 의미가 됩니다.

 

다음 assert는 값이 맞는지 확인하는 코드라고 생각하시면 됩니다.

 

assertEquals(p.getName(), "유찌") 라는 코드는 

p.getName() 메소드를 호출했을때 '유찌'가 리턴되는게 맞느냐? 라는 질문이라고 생각하시면 됩니다.

 

주석처리한 assertTrue(22 == p.getAge())는 에러를 발생하도록 하는 코드입니다.

위의 when에서 p.getAge() 메소드 호출 시 리턴값으로 1을 설정하였기 때문에 false이고 이는 에러로 이어지게 됩니다.

 

다음 verify는 검증 절차 입니다.

이 메소드가 위에서 몇 번이 실행되었는가를 확인하는 코드인데 이것 또한 글로 풀어 쓰자면

 

verify(p, times(2)).getAge() -> p.getAge() 메소드가 총 두 번이 호출 된게 맞느냐는 의미입니다.

assert 코드에서 getAge가 두 번이 나왔으므로 해당 검증 코드는 true 입니다.

 

 

마지막 verify(p).getName()은 그럼 true일까요 false 일까요?

 

 

정답은 true입니다!

when에서 p.getName()은 딱 한 번 호출되었고, verify에서 times를 지정하지 않았을 때는 default 값으로 1이 들어가기 때문입니다.

 

 

 

 

BDD라는 given when then 이라는 작성 기법이 존재합니다.

다음에는 given when then 패턴과 Controller와 Service 그리고 Dao에서 어떠한 방식으로 테스트 코드 작성을 하는지 포스팅 하겠습니다.

(본인도 아직 미숙합니다ㅠㅅㅠ..)