사용자 도구

사이트 도구


java:mockito

Mockito

argThat

argThatArgumentMatcher를 조합하여 동적인 인자 비교가 가능하다. whenverify에서 모두 사용가능하다.

이를 사용하면 특히 테스트 대상 메소드 내부에서 직접 new로 생성한 값에 대해 when에서 ArgumentCaptor없이 비교가능하여 불필요한 verify호출을 줄일 수 있다.

ArgumentMatcher 문서를 참조하면 된다.

class IsListOfTwoElements extends ArgumentMatcher<List> {
    public boolean matches(Object list) {
        return ((List) list).size() == 2;
    }
}
List mock = mock(List.class);
 
when(mock.addAll(argThat(new IsListOfTwoElements()))).thenReturn(true);
 
mock.addAll(Arrays.asList("one", "two"));
 
verify(mock).addAll(argThat(new IsListOfTwoElements()));

가능하면 argThat 부분을 메소드로 빼서 인자를 받아 ArgumentMatcher를 구성하는 것이 좋다. 아래는 문자열 List를 인자로 받을 때, 해당 리스트의 값이 모두 포함돼 있는지 검사하는 Matcher.

private List<String> sameStringList(final Collection<String> strings) {
    return argThat(new ArgumentMatcher<List<String>>() {
        @Override
        public boolean matches(Object argument) {
            List<String> args = (List<String>) argument;
            return args.size() == strings.size() && args.containsAll(strings);
        }
    });
}

when에서 동일한 모의 객체의 동일한 메소드를 두 번이상 argThat으로 호출하면 오류가 발생할 수 있다. 이 때는 doReturn 방식으로 when을 구성한다.

doReturn(리턴값).when(mockObject).mockMethod(argThat(....));

ArgumentCaptor

// MockitoRunner 사용시
@Captor
ArgumentCaptor<MyClass> myClassCaptor;
 
// 코드로 직접 지정
ArgumentCaptor<MyClass> myClassCaptor = ArgumentCaptor.forClass(MyClass.class);

initMocks

public class CalculatorApplicationTestInitMocks {
    @Mock private Adder adderMock;
    @Mock private Subtracter subtracterMock;
    @Mock private Multiplier multiplierMock;
    @Mock private Divisor divisorMock;
 
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this); // 테스트 클래스의 @Mock 애노테이션 붙은 필드에 객체들이 생서됨
        ...
    }
}

JUnit 5

@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    @Mockito ...
}
 
// Strictness 를 설정하려면 아래 추가. default가 STRICT_STUBS임. LENIENT 로 변경하기
@MockitoSettings(strictness = Strictness.LENIENT)
  • LENIENT는 좋지 잘못된 stub 을 만들고 있다는 의미가 되므로 가급적 STRICT_STUB(기본값)을 유지할것.

mockStatic

import static org.mockito.Mockito.mockStatic;
 
assertEquals("foo", Foo.method());
try (MockedStatic<Foo> mocked = mockStatic(Foo.class)) {
    mocked.when(Foo::method).thenReturn("bar");
    // 혹은 Mockito.when(Foo.method()).thenReturn("bar");
    assertEquals("bar", Foo.method());
    mocked.verify(Foo::method);
}
assertEquals("foo", Foo.method());
  • 만약 mocking 할 필요가 없는 다른 static method가 호출된다면 실제 코드를 호출하게 명시적으로 지정해야 한다.
when(LocalDateTime.from(Mockito.any())).thenCallRealMethod();

mockConstruction

  • 생성자 mocking
  • 항상 try-with-resources로 감싸서 할 것.
 assertEquals("foo", new Foo().method());
 try (MockedConstruction mocked = mockConstruction(Foo.class)) {
 Foo foo = new Foo();
 when(foo.method()).thenReturn("bar");
 assertEquals("bar", foo.method());
 verify(foo).method();
 }
 assertEquals("foo", new Foo().method());
 

참고

java/mockito.txt · 마지막으로 수정됨: 2023/11/30 14:17 저자 kwon37xi