====== 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]]