티스토리 뷰
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);
doReturn()
doReturn() 메서드는 when() 구문으로는 처리할 수 없는 특정 상황에서 매우 유용
- final 메서드를 스터빙할 때: Mockito는 기본적으로 final 메서드를 스터빙할 수 없습니다.
- void 메서드를 스터빙할 때: when() 구문은 void 메서드에 적용할 수 없습니다.
- 이미 호출된 메서드를 스터빙할 때: when() 구문은 메서드가 호출되기 전에 설정해야 합니다. 이미 호출된 메서드를 나중에 스터빙하려면 doReturn()을 사용해야 합니다.
- 내부 동작이 복잡한 메서드를 스터빙할 때: 특정한 상황에서는 when() 구문을 사용하면 예외가 발생할 수 있습니다. 이 경우 doReturn()을 사용하면 이러한 예외를 피할 수 있습니다.
final 메서드를 스터빙
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Test;
public class FinalMethodExample {
@Test
public void testFinalMethod() {
// Given
FinalClass finalClassMock = mock(FinalClass.class);
// When
doReturn("final response").when(finalClassMock).finalMethod();
// Then
String result = finalClassMock.finalMethod();
assertEquals("final response", result);
}
}
final class FinalClass {
public final String finalMethod() {
return "original response";
}
}
Void 메서드를 스터빙할 때
void 메서드에 특정 동작을 설정하거나 예외를 던지게 하려면 doReturn(), doThrow(), doNothing(), doAnswer() 등을 사용해야 합니다.
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Test;
public class VoidMethodExample {
@Test
public void testVoidMethod() {
// Given
SomeClass someClassMock = mock(SomeClass.class);
// When
doNothing().when(someClassMock).voidMethod();
// Then
someClassMock.voidMethod();
verify(someClassMock).voidMethod();
}
}
class SomeClass {
public void voidMethod() {
// Original implementation
}
}
이미 호출된 메서드를 스터빙할 때
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Test;
import java.util.List;
public class AlreadyCalledMethodExample {
@Test
public void testAlreadyCalledMethod() {
// Given
List<String> mockedList = mock(List.class);
// 메서드 호출
mockedList.get(0);
// When
doReturn("post-hoc response").when(mockedList).get(0);
// Then
String result = mockedList.get(0);
assertEquals("post-hoc response", result);
}
}
내부 동작이 복잡한 메서드를 스터빙할 때
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
import org.junit.Test;
public class ComplexInternalBehaviorExample {
@Test
public void testComplexInternalBehavior() {
// Given
SomeClass someClassMock = mock(SomeClass.class);
// 복잡한 내부 동작으로 인해 `when()`을 사용할 수 없는 경우
// When
doReturn("complex response").when(someClassMock).complexMethod();
// Then
String result = someClassMock.complexMethod();
assertEquals("complex response", result);
}
}
class SomeClass {
public String complexMethod() {
// Complex internal logic
return "original response";
}
}
@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