본문 바로가기

Backend Development/Spring boot

[Spring boot] Spring boot test시 Static class mock 만들기

JUnit으로 테스트 작성 시 Static Class를 Mocking해서 테스트를 해야할 경우가 많이 생긴다. sprin-boot-starter-test 패키지에서 기본으로 제공하는 mockito-core패키지에는 static class mocking을 위해 아래 함수를 제공한다.

MockedStatic<SecurityUtils> mockSecurityUtils = Mockito.mockStatic(SecurityUtils.class);
mockSecurityUtils.when(() -> getPlainCredential(anyString(), any())).thenReturn("1q2w3e4r5t!!");

 

Mokito.mockStatic 메소드에 Mocking을 할 static class를 지정해 주고 when, thenReturn으로 상황에 따른 출력값을 지정해 준다. 그러나 위 기본 제공 메소드를 실행해 보면 다음과 같은 에러가 발생한다.


예제 테스트 코드 실행

@SpringBootTest(properties = {"spring.profiles.active=dev"})
@ContextConfiguration
public class TestCustomer {

    @Test
    public void insertTest() {
        MockedStatic<SecurityUtils> mockSecurityUtils = Mockito.mockStatic(SecurityUtils.class);
        mockSecurityUtils.when(() -> getPlainCredential(anyString(), any())).thenReturn("1q2w3e4r5t!!");
    }
}

 

실행 결과

 

Mockito's inline mock maker supports static mocks based on the Instrumentation API.
You can simply enable this mock mode, by placing the 'mockito-inline' artifact where you are currently using 'mockito-core'.
Note that Mockito's inline mock maker is not supported on Android.

at com.sdp.service.job.sec.TestCustomer.insertTest(TestCustomer.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

 

대층 해석해보면 static mock mode를 enable 하려면 mockito-inline으로 artifact를 replacing하면 된다고 한다.

간단하게 pom.xml에 위 mockito-inline을 추가해 주면 위 에러는 사라지고 정상적으로 static mocking이 동작하게 된다.

 

아래와 같이 pom.xml에 추가해 준다.

<dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-inline</artifactId>
   <scope>test</scope>
</dependency>

 

추가로 더 고려해야할 사항은 한번 static mock을 설정해 놓으면 다른 테스트 코드에서 동일하게 static mock 사용 시 이미 사용중이라고 실행이 안된다. 따라서 테스트 코드 작성 시 try 구문을 사용해 테스트 코드 종료시 static mocking 설정이 자동 해제 되도록 하면 전체 테스트 코드 실행시에 다른 테스트에 영향 없이 static mocking을 각 테스트 코드마다 자유롭게 사용할 수 있게 된다.

 

아래 예는 try구문으로 static mocking 선언을 감싼 결과 이다.

@SpringBootTest(properties = {"spring.profiles.active=dev"})
@ContextConfiguration
public class TestCustomer {

    @Test
    public void insertTest() {
        try (MockedStatic<SecurityUtils> mockSecurityUtils = Mockito.mockStatic(SecurityUtils.class)) {
            mockSecurityUtils.when(() -> getPlainCredential(anyString(), any())).thenReturn("1q2w3e4r5t!!");

            //assert로 확인
        }
    }
}

 

-- The End --