Java/테스트

Java 테스트에서의 Mocking 라이브러리

고기고기물고기 2024. 9. 9. 11:33

MockitoJava에서 단위 테스트를 작성할 때 가장 널리 사용되는 Mocking 라이브러리 중 하나입니다. 단위 테스트에서 객체 간의 의존성 문제를 해결하기 위해 Mock 객체를 사용하여 실제 객체의 동작을 모의(Mock)할 수 있도록 도와줍니다. 이를 통해 독립적인 테스트를 수행하고, 외부 시스템이나 데이터베이스와의 의존성을 제거할 수 있습니다.

 

1. Mockito란?

MockitoMock 객체를 쉽게 생성하고 관리할 수 있도록 도와주는 Mocking 라이브러리입니다. 이 라이브러리는 주로 단위 테스트에서 의존성 주입된 객체의 동작을 모의하여 실제 객체와의 상호작용을 테스트할 때 사용됩니다.

Mock 객체는 실제 동작을 대체하여, 테스트하려는 대상 객체만 독립적으로 테스트할 수 있게 합니다. 예를 들어, 데이터베이스나 외부 서비스에 의존하는 메서드를 테스트할 때, 해당 의존성을 Mock 객체로 대체하여 네트워크나 데이터베이스 의존성 없이 메서드를 검증할 수 있습니다.

 

2. Mockito의 주요 기능

1) Mock 객체 생성

Mockito를 사용하면 실제 객체 대신 사용할 Mock 객체를 생성할 수 있습니다. Mock 객체는 실제 객체와 동일한 인터페이스를 가지지만, 동작은 테스트에서 정의된 대로 수행됩니다.

MyService mockService = Mockito.mock(MyService.class);
 

위 코드는 MyService 클래스의 Mock 객체를 생성하는 예시입니다.

 

3) 메서드 호출 검증

Mockito는 특정 메서드가 호출되었는지 여부를 검증할 수 있습니다. 메서드가 몇 번 호출되었는지, 어떤 파라미터로 호출되었는지를 확인할 수 있습니다.

예시:

verify(mockService).getData(); // getData()가 호출되었는지 검증
 

위 코드는 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() 호출 여부 검증
    }
}

 

JUnitMockito를 통합하여 Mock 객체를 주입하고, 그 동작을 모의하며, 최종적으로 메서드 호출 검증까지 진행하는 예시입니다.

 

 

Mockito: Java 테스트에서의 Mocking 라이브러리

MockitoJava에서 단위 테스트를 작성할 때 가장 널리 사용되는 Mocking 라이브러리 중 하나입니다. 단위 테스트에서 객체 간의 의존성 문제를 해결하기 위해 Mock 객체를 사용하여 실제 객체의 동작을 모의(Mock)할 수 있도록 도와줍니다. 이를 통해 독립적인 테스트를 수행하고, 외부 시스템이나 데이터베이스와의 의존성을 제거할 수 있습니다.


목차

  1. Mockito란?
  2. Mockito의 주요 기능
    • Mock 객체 생성
    • Stubbing
    • 메서드 호출 검증
    • Spy 객체
  3. JUnit과 Mockito의 통합
  4. Mockito 어노테이션
  5. Mockito의 장점
  6. 예제 코드
  7. 결론

1. Mockito란?

MockitoMock 객체를 쉽게 생성하고 관리할 수 있도록 도와주는 Mocking 라이브러리입니다. 이 라이브러리는 주로 단위 테스트에서 의존성 주입된 객체의 동작을 모의하여 실제 객체와의 상호작용을 테스트할 때 사용됩니다.

Mock 객체는 실제 동작을 대체하여, 테스트하려는 대상 객체만 독립적으로 테스트할 수 있게 합니다. 예를 들어, 데이터베이스나 외부 서비스에 의존하는 메서드를 테스트할 때, 해당 의존성을 Mock 객체로 대체하여 네트워크나 데이터베이스 의존성 없이 메서드를 검증할 수 있습니다.


2. Mockito의 주요 기능

1) Mock 객체 생성

Mockito를 사용하면 실제 객체 대신 사용할 Mock 객체를 생성할 수 있습니다. Mock 객체는 실제 객체와 동일한 인터페이스를 가지지만, 동작은 테스트에서 정의된 대로 수행됩니다.

예시:

java
코드 복사
MyService mockService = Mockito.mock(MyService.class);

위 코드는 MyService 클래스의 Mock 객체를 생성하는 예시입니다.

2) Stubbing

Stubbing은 Mock 객체의 특정 메서드가 호출되었을 때 반환할 값을 정의하는 것을 의미합니다. 테스트에서는 Mock 객체의 메서드가 호출될 때 어떤 값이 반환되어야 할지 명시할 수 있습니다.

예시:

java
코드 복사
// when 메서드로 호출될 때의 동작 정의 when(mockService.getData()).thenReturn("Mocked Data");

위 코드는 mockService.getData()가 호출될 때 "Mocked Data"를 반환하도록 설정하는 Stubbing 예시입니다.

3) 메서드 호출 검증

Mockito는 특정 메서드가 호출되었는지 여부를 검증할 수 있습니다. 메서드가 몇 번 호출되었는지, 어떤 파라미터로 호출되었는지를 확인할 수 있습니다.

예시:

java
코드 복사
verify(mockService).getData(); // getData()가 호출되었는지 검증

위 코드는 getData() 메서드가 한 번 호출되었는지 검증하는 코드입니다.

4) Spy 객체

Spy는 실제 객체의 일부 동작을 Mocking할 수 있게 해줍니다. 즉, 특정 메서드만 모의하고, 나머지 메서드는 실제 동작을 유지할 수 있습니다.

예시:

java
코드 복사
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() 호출 여부 검증
    }
}

 

JUnitMockito를 통합하여 Mock 객체를 주입하고, 그 동작을 모의하며, 최종적으로 메서드 호출 검증까지 진행하는 예시입니다.

4. Mockito 어노테이션

Mockito는 여러 편리한 어노테이션을 제공합니다. 이를 통해 Mock 객체를 쉽게 주입하고, 테스트 클래스의 가독성을 높일 수 있습니다.

주요 어노테이션:

  • @Mock: Mock 객체를 생성합니다.
  • @InjectMocks: Mock 객체를 주입받을 객체를 생성하고, 주입합니다.
  • @Spy: 특정 객체를 부분적으로 모의할 때 사용합니다.

5. Mockito의 장점

  1. 의존성 제거: 외부 시스템(데이터베이스, 파일 시스템, 네트워크 등)에 대한 의존성을 제거하여, 독립적인 단위 테스트를 가능하게 합니다.
  2. 테스트 실행 속도 향상: 실제 객체를 사용하지 않고 Mock 객체를 사용하므로, 테스트 속도가 빨라집니다.
  3. 객체의 동작을 세밀하게 제어: Mock 객체의 동작을 세밀하게 제어할 수 있어, 다양한 시나리오를 테스트할 수 있습니다.
  4. 테스트 작성 용이: 의존성을 쉽게 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 메서드 호출 검증
    }
}