Java 테스트에서의 Mocking 라이브러리
Mockito는 Java에서 단위 테스트를 작성할 때 가장 널리 사용되는 Mocking 라이브러리 중 하나입니다. 단위 테스트에서 객체 간의 의존성 문제를 해결하기 위해 Mock 객체를 사용하여 실제 객체의 동작을 모의(Mock)할 수 있도록 도와줍니다. 이를 통해 독립적인 테스트를 수행하고, 외부 시스템이나 데이터베이스와의 의존성을 제거할 수 있습니다.
1. Mockito란?
Mockito는 Mock 객체를 쉽게 생성하고 관리할 수 있도록 도와주는 Mocking 라이브러리입니다. 이 라이브러리는 주로 단위 테스트에서 의존성 주입된 객체의 동작을 모의하여 실제 객체와의 상호작용을 테스트할 때 사용됩니다.
Mock 객체는 실제 동작을 대체하여, 테스트하려는 대상 객체만 독립적으로 테스트할 수 있게 합니다. 예를 들어, 데이터베이스나 외부 서비스에 의존하는 메서드를 테스트할 때, 해당 의존성을 Mock 객체로 대체하여 네트워크나 데이터베이스 의존성 없이 메서드를 검증할 수 있습니다.
2. Mockito의 주요 기능
1) Mock 객체 생성
Mockito를 사용하면 실제 객체 대신 사용할 Mock 객체를 생성할 수 있습니다. Mock 객체는 실제 객체와 동일한 인터페이스를 가지지만, 동작은 테스트에서 정의된 대로 수행됩니다.
MyService mockService = Mockito.mock(MyService.class);
위 코드는 MyService 클래스의 Mock 객체를 생성하는 예시입니다.
3) 메서드 호출 검증
Mockito는 특정 메서드가 호출되었는지 여부를 검증할 수 있습니다. 메서드가 몇 번 호출되었는지, 어떤 파라미터로 호출되었는지를 확인할 수 있습니다.
예시:
위 코드는 getData() 메서드가 한 번 호출되었는지 검증하는 코드입니다.
4) Spy 객체
Spy는 실제 객체의 일부 동작을 Mocking할 수 있게 해줍니다. 즉, 특정 메서드만 모의하고, 나머지 메서드는 실 제 동작을 유지할 수 있습니다.
예시:
MyService realService = new MyService(); MyService spyService = Mockito.spy(realService); // 특정 메서드만
Mocking when(spyService.getData()).thenReturn("Mocked Data");
이 코드에서는 spyService가 realService 객체를 기반으로 하며, getData() 메서드만 모의하고 나머지는 실제 동작을 유지합니다.
3. JUnit과 Mockito의 통합
Mockito는 JUnit과 잘 통합되어 사용됩니다. JUnit은 테스트 프레임워크로 테스트 케이스를 작성하고 실행하는 역할을 하고, Mockito는 테스트에서 Mock 객체를 사용하여 의존성을 제거하는 역할을 합니다.
Mockito와 JUnit 통합 예시:
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class) // JUnit과 Mockito 통합
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService; // Mock 객체가 주입된 서비스
@Test
void testGetData() {
// Stubbing: Mock 객체 동작 정의
when(myRepository.getData()).thenReturn("Mocked Data");
// 메서드 실행
String result = myService.getData();
// 검증
assertEquals("Mocked Data", result);
verify(myRepository).getData(); // getData() 호출 여부 검증
}
}
JUnit과 Mockito를 통합하여 Mock 객체를 주입하고, 그 동작을 모의하며, 최종적으로 메서드 호출 검증까지 진행하는 예시입니다.
Mockito: Java 테스트에서의 Mocking 라이브러리
Mockito는 Java에서 단위 테스트를 작성할 때 가장 널리 사용되는 Mocking 라이브러리 중 하나입니다. 단위 테스트에서 객체 간의 의존성 문제를 해결하기 위해 Mock 객체를 사용하여 실제 객체의 동작을 모의(Mock)할 수 있도록 도와줍니다. 이를 통해 독립적인 테스트를 수행하고, 외부 시스템이나 데이터베이스와의 의존성을 제거할 수 있습니다.
목차
- Mockito란?
- Mockito의 주요 기능
- Mock 객체 생성
- Stubbing
- 메서드 호출 검증
- Spy 객체
- JUnit과 Mockito의 통합
- Mockito 어노테이션
- Mockito의 장점
- 예제 코드
- 결론
1. Mockito란?
Mockito는 Mock 객체를 쉽게 생성하고 관리할 수 있도록 도와주는 Mocking 라이브러리입니다. 이 라이브러리는 주로 단위 테스트에서 의존성 주입된 객체의 동작을 모의하여 실제 객체와의 상호작용을 테스트할 때 사용됩니다.
Mock 객체는 실제 동작을 대체하여, 테스트하려는 대상 객체만 독립적으로 테스트할 수 있게 합니다. 예를 들어, 데이터베이스나 외부 서비스에 의존하는 메서드를 테스트할 때, 해당 의존성을 Mock 객체로 대체하여 네트워크나 데이터베이스 의존성 없이 메서드를 검증할 수 있습니다.
2. Mockito의 주요 기능
1) Mock 객체 생성
Mockito를 사용하면 실제 객체 대신 사용할 Mock 객체를 생성할 수 있습니다. Mock 객체는 실제 객체와 동일한 인터페이스를 가지지만, 동작은 테스트에서 정의된 대로 수행됩니다.
예시:
위 코드는 MyService 클래스의 Mock 객체를 생성하는 예시입니다.
2) Stubbing
Stubbing은 Mock 객체의 특정 메서드가 호출되었을 때 반환할 값을 정의하는 것을 의미합니다. 테스트에서는 Mock 객체의 메서드가 호출될 때 어떤 값이 반환되어야 할지 명시할 수 있습니다.
예시:
위 코드는 mockService.getData()가 호출될 때 "Mocked Data"를 반환하도록 설정하는 Stubbing 예시입니다.
3) 메서드 호출 검증
Mockito는 특정 메서드가 호출되었는지 여부를 검증할 수 있습니다. 메서드가 몇 번 호출되었는지, 어떤 파라미터로 호출되었는지를 확인할 수 있습니다.
예시:
위 코드는 getData() 메서드가 한 번 호출되었는지 검증하는 코드입니다.
4) Spy 객체
Spy는 실제 객체의 일부 동작을 Mocking할 수 있게 해줍니다. 즉, 특정 메서드만 모의하고, 나머지 메서드는 실제 동작을 유지할 수 있습니다.
예시:
이 코드에서는 spyService가 realService 객체를 기반으로 하며, getData() 메서드만 모의하고 나머지는 실제 동작을 유지합니다.
3. JUnit과 Mockito의 통합
Mockito는 JUnit과 잘 통합되어 사용됩니다. JUnit은 테스트 프레임워크로 테스트 케이스를 작성하고 실행하는 역할을 하고, Mockito는 테스트에서 Mock 객체를 사용하여 의존성을 제거하는 역할을 합니다.
Mockito와 JUnit 통합 예시:
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(MockitoExtension.class) // JUnit과 Mockito 통합
public class MyServiceTest {
@Mock
private MyRepository myRepository;
@InjectMocks
private MyService myService; // Mock 객체가 주입된 서비스
@Test
void testGetData() {
// Stubbing: Mock 객체 동작 정의
when(myRepository.getData()).thenReturn("Mocked Data");
// 메서드 실행
String result = myService.getData();
// 검증
assertEquals("Mocked Data", result);
verify(myRepository).getData(); // getData() 호출 여부 검증
}
}
JUnit과 Mockito를 통합하여 Mock 객체를 주입하고, 그 동작을 모의하며, 최종적으로 메서드 호출 검증까지 진행하는 예시입니다.
4. Mockito 어노테이션
Mockito는 여러 편리한 어노테이션을 제공합니다. 이를 통해 Mock 객체를 쉽게 주입하고, 테스트 클래스의 가독성을 높일 수 있습니다.
주요 어노테이션:
- @Mock: Mock 객체를 생성합니다.
- @InjectMocks: Mock 객체를 주입받을 객체를 생성하고, 주입합니다.
- @Spy: 특정 객체를 부분적으로 모의할 때 사용합니다.
5. Mockito의 장점
- 의존성 제거: 외부 시스템(데이터베이스, 파일 시스템, 네트워크 등)에 대한 의존성을 제거하여, 독립적인 단위 테스트를 가능하게 합니다.
- 테스트 실행 속도 향상: 실제 객체를 사용하지 않고 Mock 객체를 사용하므로, 테스트 속도가 빨라집니다.
- 객체의 동작을 세밀하게 제어: Mock 객체의 동작을 세밀하게 제어할 수 있어, 다양한 시나리오를 테스트할 수 있습니다.
- 테스트 작성 용이: 의존성을 쉽게 Mocking 할 수 있어, 테스트 코드 작성이 간편하고 가독성이 높아집니다.
서비스 테스트 예시:
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class)
public class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void testGetUserById() {
// Stubbing
when(userRepository.findById(1L)).thenReturn(new User(1L, "John Doe"));
// 메서드 실행
User user = userService.getUserById(1L);
// 검증
assertEquals("John Doe", user.getName());
verify(userRepository).findById(1L); // findById 메서드 호출 검증
}
}