[java] Mockito를 사용하여 특정 메소드에 전달된 인자들로 다른 메소드를 호출할 때 실행 중인 스레드를 모킹하는 방법은?
- Mockito를 프로젝트에 추가합니다. Maven을 사용한다면 pom.xml에 다음 의존성을 추가하세요.
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.8.0</version>
<scope>test</scope>
</dependency>
- 실행 중인 스레드를 모킹하기 위해
Thread
클래스를 확장한 모킹 클래스를 작성합니다.
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class MockThread extends Thread {
private static final Thread MAIN_THREAD = new MockThread();
public static void mockCurrentThread() {
Mockito.mockStatic(Thread.class);
Mockito.when(Thread.currentThread()).thenReturn(MAIN_THREAD);
Mockito.when(Thread.currentThread().isAlive()).thenReturn(true);
Mockito.when(Thread.currentThread().getName()).thenReturn("main");
}
public static void cleanupMock() {
Mockito.mockStatic(Thread.class).close();
}
public static void resetMock() {
Mockito.reset(MAIN_THREAD);
}
@Override
public void run() {
// 꼭 필요한 경우에만 오버라이드
super.run();
}
@Override
public String toString() {
return MAIN_THREAD.toString();
}
@Override
public int hashCode() {
return MAIN_THREAD.hashCode();
}
@Override
public boolean equals(Object obj) {
return MAIN_THREAD.equals(obj);
}
// 특정 메소드 호출 시 원하는 결과를 반환하는 예제
public static Answer<?> answer(Object expectedValue) {
return new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
return expectedValue;
}
};
}
}
- 테스트를 작성할 클래스에서
MockThread.mockCurrentThread()
를 호출하여 특정 메소드를 호출하는 부분을 모킹하고 스레드를 실행 중인 것처럼 동작하도록 만들 수 있습니다.
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;
public class MyTestClass {
@BeforeEach
public void setup() {
MockThread.mockCurrentThread();
}
@AfterEach
public void cleanup() {
MockThread.cleanupMock();
}
@Test
public void testMyMethod() {
// Arrange
MyObject myObject = mock(MyObject.class);
doAnswer(MockThread.answer(42)).when(myObject).myMethod(anyString());
// Act
// 실행 중인 스레드인 것처럼 동작하도록 호출
myObject.myMethod("test");
// Assert
// 모킹한 메소드가 실행되었는지 확인
verify(myObject).myMethod(anyString());
// 원하는 결과를 반환하는지 확인
assertEquals(42, myObject.getResult());
}
}
위의 예시 코드에서 MyObject
는 특정 메소드를 갖는 클래스입니다. MyObject
의 myMethod()
가 호출될 때, Thread.currentThread()
를 호출하더라도 MockThread.MAIN_THREAD
를 반환하도록 모킹되어 있습니다. 이를 통해 실행 중인 스레드를 모킹할 수 있습니다.
테스트 코드에서는 MyObject
를 mock()
으로 모킹한 뒤, doAnswer()
를 사용하여 myMethod()
가 호출되었을 때 원하는 결과를 반환하도록 설정하였습니다. 이후에는 myObject
에서 myMethod()
를 호출하고, 원하는 결과를 반환하는지 확인하는 테스트를 수행하였습니다.
추가로, MockThread
클래스에는 스레드와 관련된 다른 메소드들을 모킹한 예제도 포함되어 있습니다. 이를 통해 필요한 경우에 다양한 스레드 관련 동작을 모킹할 수 있습니다.
테스트 코드에서 @BeforeEach
와 @AfterEach
어노테이션을 사용하여 테스트 메소드를 실행하기 전과 후에 스레드 모킹과 관련된 초기화와 클린업을 수행하도록 했습니다.
이렇게 Mockito와 MockThread를 사용하여 특정 메소드에 전달된 인자들로 다른 메소드를 호출할 때 실행 중인 스레드를 모킹할 수 있습니다.
참고 자료
- Mockito 공식 문서: https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
- Mockito GitHub 저장소: https://github.com/mockito/mockito