====== Mockito ======
* [[https://github.com/mockito/mockito|Mockito]]
* https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
* [[https://dzone.com/refcardz/mockito|Mockito RefCard]]
* [[https://examples.javacodegeeks.com/core-java/mockito/mockito-tutorial-beginners/|Mockito Tutorial for beginners]]
===== argThat =====
''argThat''과 [[http://mockito.github.io/mockito/docs/current/org/mockito/ArgumentMatcher.html|ArgumentMatcher]]를 조합하여 동적인 인자 비교가 가능하다. ''when''과 ''verify''에서 모두 사용가능하다.
이를 사용하면 특히 테스트 대상 메소드 내부에서 직접 ''new''로 생성한 값에 대해 ''when''에서 ''ArgumentCaptor''없이 비교가능하여 불필요한 ''verify''호출을 줄일 수 있다.
[[http://mockito.github.io/mockito/docs/current/org/mockito/ArgumentMatcher.html|ArgumentMatcher]] 문서를 참조하면 된다.
class IsListOfTwoElements extends ArgumentMatcher {
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 sameStringList(final Collection strings) {
return argThat(new ArgumentMatcher>() {
@Override
public boolean matches(Object argument) {
List args = (List) argument;
return args.size() == strings.size() && args.containsAll(strings);
}
});
}
''when''에서 동일한 모의 객체의 동일한 메소드를 두 번이상 ''argThat''으로 호출하면 오류가 발생할 수 있다. 이 때는 ''doReturn'' 방식으로 ''when''을 구성한다.
doReturn(리턴값).when(mockObject).mockMethod(argThat(....));
===== ArgumentCaptor =====
* [[https://www.baeldung.com/mockito-argumentcaptor|Using Mockito ArgumentCaptor | Baeldung]]
// MockitoRunner 사용시
@Captor
ArgumentCaptor myClassCaptor;
// 코드로 직접 지정
ArgumentCaptor myClassCaptor = ArgumentCaptor.forClass(MyClass.class);
===== initMocks =====
* [[https://examples.javacodegeeks.com/core-java/mockito/initializing-mockito-with-initmocks/|Initializing Mockito with InitMocks]]
* ''@RunWIth''없이 일괄 ''@Mock'' 객체 생성하기
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 =====
* [[java:junit:5|JUnit 5]]와 함께 사용.
* [[https://www.baeldung.com/mockito-junit-5-extension|Mockito and JUnit 5 - Using ExtendWith | Baeldung]]
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mockito ...
}
// Strictness 를 설정하려면 아래 추가. default가 STRICT_STUBS임. LENIENT 로 변경하기
@MockitoSettings(strictness = Strictness.LENIENT)
* ''LENIENT''는 좋지 잘못된 stub 을 만들고 있다는 의미가 되므로 가급적 ''STRICT_STUB''(기본값)을 유지할것.
===== mockStatic =====
* Mockito ''3.4.0'' 이상 버전 지원
* static method mocking. 특히 ''LocalDateTime.now()'' 테스트 등에 좋다.
* [[https://www.baeldung.com/mockito-mock-static-methods|Mocking Static Methods With Mockito | Baeldung]]
* 항상 ''try-with-resources''로 감싸서 할 것.
import static org.mockito.Mockito.mockStatic;
assertEquals("foo", Foo.method());
try (MockedStatic 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());
===== 참고 =====
* [[http://www.javacodegeeks.com/2015/11/mockito-verification.html|Mockito Verification]]
* [[http://www.javacodegeeks.com/2015/11/testing-with-mockito.html|Mockito Tutorial: Testing and Mocking with Mockito]]
* [[http://www.javacodegeeks.com/2015/12/using-mockito-without-static-imports-java-8.html|Using Mockito without static imports with Java 8]]
* [[https://www.baeldung.com/mockito-core-vs-mockito-all|The Difference Between mockito-core and mockito-all | Baeldung]]
* [[https://www.baeldung.com/mockito-spy|Mockito using Spy]]
* [[https://www.baeldung.com/mockito-argument-matchers|Mockito ArgumentMatchers | Baeldung]]
* [[https://www.baeldung.com/mockito-mock-static-methods|Mocking Static Methods With Mockito | Baeldung]]
* [[https://www.baeldung.com/java-override-system-time|Overriding System Time for Testing in Java | Baeldung]]