티스토리 뷰

Java

[Java] Mockito Framework Spy, ArgumentCaptor

snail voyager 2024. 3. 31. 23:47
728x90
반응형

spy()

spy() 메서드를 사용하면 실제 객체의 일부 기능을 유지하면서 일부만 Mock으로 대체할 수 있습니다.

이는 실제 객체의 일부 메서드 동작을 유지하면서, 특정 메서드 호출에 대한 Mock 동작을 정의할 때 유용합니다.

List list = new LinkedList();
List spy = spy(list);

//optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);

//using the spy calls *real* methods
spy.add("one");
spy.add("two");

//prints "one" - the first element of a list
System.out.println(spy.get(0));

//size() method was stubbed - 100 is printed
System.out.println(spy.size());

//optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");

when() 으로 실제 메서드가 stubbing 불가능하다면 doReturn|Answer|Throw() 를 사용한다.

List list = new LinkedList();
List spy = spy(list);

//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");

//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);

@Spy

spy() 메서드 대신에 @Spy로 spy 객체를 생성할 수 있다.

import org.mockito.Spy;

public class ExampleTest {

    @Spy
    Calculator spyCalculator;

    @Test
    public void testSpy() {
        // spyCalculator 객체의 일부 메서드의 동작을 유지하면서 일부 Mock 동작 정의
        doReturn(10).when(spyCalculator).add(2, 3);

        // 테스트
        int result = spyCalculator.add(2, 3);

        // 결과 확인
        assertEquals(10, result);

        // 실제 add 메서드가 호출되었는지 확인
        verify(spyCalculator).add(2, 3);

        // 나머지 add 메서드는 실제 객체의 동작을 유지
        assertEquals(7, spyCalculator.add(3, 4)); // 실제 add 메서드 호출
    }
}

ArgumentCaptor

메서드 호출 시 전달된 인자를 캡처하고 이를 검증하는 데 사용됩니다. 

주로 메서드 호출에 대한 매개변수를 확인하거나 특정 인자에 대한 검증을 수행할 때 유용합니다.

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;

public class ExampleTest {

    @Test
    public void testAddMethodWithArgumentCaptor() {
        // Mock 객체 생성
        Calculator calculator = mock(Calculator.class);

        // ArgumentCaptor 생성
        ArgumentCaptor<Integer> arg1Captor = ArgumentCaptor.forClass(Integer.class);
        ArgumentCaptor<Integer> arg2Captor = ArgumentCaptor.forClass(Integer.class);

        // 특정 메서드 호출 시 전달되는 인자를 캡처
        calculator.add(2, 3);

        // 캡처한 인자를 검증
        verify(calculator).add(arg1Captor.capture(), arg2Captor.capture());
        
        // 캡처한 인자 값 확인
        assertEquals(2, arg1Captor.getValue());
        assertEquals(3, arg2Captor.getValue());
    }
}

@Captor

@Captor 어노테이션을 필드에 적용하면 Mockito가 자동으로 해당 필드를 초기화하고 적절한 유형의 ArgumentCaptor를 할당합니다.

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

import org.junit.jupiter.api.Test;
import org.mockito.Captor;
import org.mockito.MockitoAnnotations;
import org.mockito.ArgumentCaptor;

public class ExampleTest {

    @Captor
    private ArgumentCaptor<Integer> arg1Captor;

    @Captor
    private ArgumentCaptor<Integer> arg2Captor;

    @Test
    public void testAddMethodWithArgumentCaptor() {
        // MockitoAnnotations.initMocks()를 사용하여 @Captor 필드 초기화
        MockitoAnnotations.initMocks(this);

        // Mock 객체 생성
        Calculator calculator = mock(Calculator.class);

        // 특정 메서드 호출 시 전달되는 인자를 캡처
        calculator.add(2, 3);

        // 캡처한 인자를 검증
        verify(calculator).add(arg1Captor.capture(), arg2Captor.capture());
        
        // 캡처한 인자 값 확인
        assertEquals(2, arg1Captor.getValue());
        assertEquals(3, arg2Captor.getValue());
    }
}
728x90
반응형

'Java' 카테고리의 다른 글

[Java] Mustache Template Rendering  (0) 2024.04.03
[Java] Object Mapping Frameworks 성능 비교  (0) 2024.04.02
[Java] Garbage Collector 개념  (0) 2024.02.19
[Java] 마이크로벤치마킹 JMH  (0) 2024.02.17
[Java] JVM  (0) 2024.02.17
반응형
300x250