source

Mockito는 여러 번 호출된 메서드의 인수를 캡처할 수 있습니까?

factcode 2022. 11. 5. 08:58
반응형

Mockito는 여러 번 호출된 메서드의 인수를 캡처할 수 있습니까?

두 번 호출되는 메서드가 있는데 두 번째 메서드 호출 인수를 캡처하고 싶습니다.

제가 시도한 것은 다음과 같습니다.

ArgumentCaptor<Foo> firstFooCaptor = ArgumentCaptor.forClass(Foo.class);
ArgumentCaptor<Foo> secondFooCaptor = ArgumentCaptor.forClass(Foo.class);
verify(mockBar).doSomething(firstFooCaptor.capture());
verify(mockBar).doSomething(secondFooCaptor.capture());
// then do some assertions on secondFooCaptor.getValue()

하지만 난...TooManyActualInvocations예외, 모키토가 생각하는 것처럼doSomething한 번만 호출해야 합니다.

의 두 번째 콜 인수를 확인하려면 어떻게 해야 합니까?doSomething?

그래야 할 것 같아요.

verify(mockBar, times(2)).doSomething(...)

mockito javadoc 샘플:

ArgumentCaptor<Person> peopleCaptor = ArgumentCaptor.forClass(Person.class);
verify(mock, times(2)).doSomething(peopleCaptor.capture());

List<Person> capturedPeople = peopleCaptor.getAllValues();
assertEquals("John", capturedPeople.get(0).getName());
assertEquals("Jane", capturedPeople.get(1).getName());

Mockito 2.0 이후 정적 메서드 Matchers.arg That(Argument Matcher)을 사용할 수도 있습니다.Java 8의 도움으로 보다 깔끔하고 읽기 쉽게 되었습니다.

verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("OneSurname")));
verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("AnotherSurname")));

Java 버전보다 낮은 버전을 사용해야 한다면, 그 정도도 나쁘지 않습니다.

verify(mockBar).doSth(argThat(new ArgumentMatcher<Employee>() {
        @Override
        public boolean matches(Object emp) {
            return ((Employee) emp).getSurname().equals("SomeSurname");
        }
    }));

물론 이들 중 어느 것도 콜 순서를 확인할 수 없습니다.InOrder를 사용해야 합니다.

InOrder inOrder = inOrder(mockBar);

inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("FirstSurname")));
inOrder.verify(mockBar).doSth(argThat((arg) -> arg.getSurname().equals("SecondSurname")));

다음과 같은 전화를 할 수 있는 mockito-java8 프로젝트를 봐주세요.

verify(mockBar).doSth(assertArg(arg -> assertThat(arg.getSurname()).isEqualTo("Surname")));

에의 모든 콜을 검증하고 싶지 않은 경우doSomething(), 마지막 1개만 사용할 수 있습니다.ArgumentCaptor.getValue(). Mockito javadoc에 따르면:

메서드가 여러 번 호출된 경우 마지막으로 캡처된 값이 반환됩니다.

이 방법은 유효합니다(전제:Foo방법이 있다getName()):

ArgumentCaptor<Foo> fooCaptor = ArgumentCaptor.forClass(Foo.class);
verify(mockBar, times(2)).doSomething(fooCaptor.capture());
//getValue() contains value set in second call to doSomething()
assertEquals("2nd one", fooCaptor.getValue().getName());

@Captor 주석이 달린 ArgumentCaptor를 사용할 수도 있습니다.예를 들어 다음과 같습니다.

@Mock
List<String> mockedList;

@Captor
ArgumentCaptor<String> argCaptor;

@BeforeTest
public void init() {
    //Initialize objects annotated with @Mock, @Captor and @Spy.
    MockitoAnnotations.initMocks(this);
}

@Test
public void shouldCallAddMethodTwice() {
    mockedList.add("one");
    mockedList.add("two");
    Mockito.verify(mockedList, times(2)).add(argCaptor.capture());

    assertEquals("one", argCaptor.getAllValues().get(0));
    assertEquals("two", argCaptor.getAllValues().get(1));
}

자바8의 람다와 함께, 편리한 방법은

org.mockito.invocation.InvocationOnMock

when(client.deleteByQuery(anyString(), anyString())).then(invocationOnMock -> {
    assertEquals("myCollection", invocationOnMock.getArgument(0));
    assertThat(invocationOnMock.getArgument(1), Matchers.startsWith("id:"));
}

우선, 항상 mockito static을 Import 해 주세요.이렇게 하면, 코드의 판독성이 향상해, 직감적으로 사용할 수 있습니다.아래의 코드 샘플에서는, 동작하기 위해서 필요합니다.

import static org.mockito.Mockito.*;

verify() 메서드에서는 Argument Captor를 전달하여 테스트 실행을 보증하고 Argument Captor를 전달하여 인수를 평가할 수 있습니다.

ArgumentCaptor<MyExampleClass> argument = ArgumentCaptor.forClass(MyExampleClass.class);
verify(yourmock, atleast(2)).myMethod(argument.capture());

List<MyExampleClass> passedArguments = argument.getAllValues();

for (MyExampleClass data : passedArguments){
    //assertSometing ...
    System.out.println(data.getFoo());
}

테스트 중에 전달된 모든 인수 목록은 인수.getAllValues() 메서드를 통해 액세스할 수 있습니다.

단일(마지막 호출된) 인수 값은 argument.getValue()를 통해 액세스할 수 있으며 추가 조작/체크 또는 원하는 작업을 수행할 수 있습니다.

언급URL : https://stackoverflow.com/questions/5981605/can-mockito-capture-arguments-of-a-method-called-multiple-times

반응형