Mockito로 static method mock 하기
지금까지 개발을 하면서 테스트 코드 짜는 것을 같이 병행하지 않았지만 최근 들어 테스트 코드를 작성하는 버릇을 들이기 시작했다.
그 중 메소드 분리 및 알맞은 접근제어자를 사용하기 위해서는 단위 테스트가 중요한데,
이 단위 테스트를 하다보면 당연히 해당 로직과는 상관없는 DI 되는 다른 객체들의 로직을 무시하기 위해 Mockito를 사용하게 된다.
static 함수 처리의 경우 PowerMokito 또는 MockedStatic을 이용하는 방법 이렇게 두 가지가 있는데 여기서는 MockedStatic을 이용하는 방법에 대해 정리해보겠다.
mockito core, inline dependency
MockedStatic은 mockito 안에 있는 클래스이다.
스프링부트 프로젝트(모듈)을 생성하면 기본으로 spring-boot-starter-test를 사용해 테스트 코드를 작성하게 된다.
이 안에 mockito 또한 포함되어 있으나 사용하는 스프링부트 버전에 따라 MockedStatic을 지원하지 않는 mockito 버전을 제공할 수 있다.
따라서 MockedStatic을 사용할 수 없다면 spring-boot-starter-test와는 별개로 mockito-cord, mockito-inline의 의존성을 추가해준다.
MockedStatic은 mockito 3.4.0 부터 지원(2020년 7월)하는 것으로 아래와 같이 그 이상의 버전을 사용해준다.
- gradle
testImplementation group: 'org.mockito', name: 'mockito-inline', version: '3.12.4'
testImplementation group: 'org.mockito', name: 'mockito-core', version: '4.3.1'
- maven
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>4.3.1</version>
<scope>test</scope>
</dependency>
static void method ignore
위와 같이 의존성을 추가하고나면 이제 MockedStatic을 사용할 수 있다.
우선 static 함수 중에서 리턴 값이 없는 함수는 해당 함수가 있는 객체를 Mockito로 감싸서 MockedStatic으로 만들어주는 것만으로 해결이 된다.
구글링을 해보면 void method도 value return method와 똑같은 방식으로 when-do를 사용해서 mock 처리해야하는 걸로 알고 질문 하는 것들이 있는데 void method의 경운 반환 값이 없기 때문에 when-do 처리가 필요 없다!
...
import org.mockito.MockedStatic;
...
public class StaticTest {
private MockedStatic<StaticClass> staticClassMock;
@Before
public void init() {
staticClassMock = Mockito.mockStatic(StaticClass.class);
}
...
만일 아래와 같이 StaticClass와 TestBO가 구성되어 있으면 TestBO의 test를 단위 테스트 하는데에 StaticClass를 제외시켜야하니 doSomething()을 아무 동작도 안 하고 넘어가야한다.
public class StaticClass {
public static void doSomething() {
// 여러가지 로직
}
}
...
@RequiredArgsConstructor
public class TestBO {
private final StaticClass staticClass;
public void test {
...
staticClass.doSomething();
...
}
}
static return value method ignore
반환 값이 있는 함수의 경우는 void method와 마찬가지로 해당 객체의 mock 처리를 우선 하고 when-do 처리를 해줘야한다.
...
import org.mockito.MockedStatic;
...
public class StaticTest {
private MockedStatic<StaticClass> staticClassMock;
@Before
public void init() {
staticClassMock = Mockito.mockStatic(StaticClass.class);
}
...
when-do 처리의 경우 해당 테스트 케이스에 맞게 when-do 처리를 통해 테스트에 필요한 결과가 나오게 하면 된다.
예를 들어 StaticClass의 test2 함수에서 String value를 반환해준다고 했을 때 아래와 같이 처리해줄 수 있다. 또는 doNothing()을 이용해 함수가 아무 동작을 하지 않고 지나가게 할 수도 있다.
(아래 코드는 junit4 기준으로 작성한 코드이다.)
...
import org.junit.Assert.*;
...
@Test
public void staticTest2() {
doReturn("success!!").when(staticClassMock).test2();
...
}
✋ Mokito Core
https://mvnrepository.com/artifact/org.mockito/mockito-core
✋ Mokito Inline
https://mvnrepository.com/artifact/org.mockito/mockito-inline
✋ MockedStatic
https://javadoc.io/static/org.mockito/mockito-core/3.4.3/org/mockito/MockedStatic.html