[java] 모키 토. 메소드 인수 확인

나는 이것에 대해 봤지만 관련성이 없었습니다. 나는 이와 같은 것을 가지고있다 :

Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj )).thenReturn(null);

Testeable testableObj = new Testeable();
testableObj.setMockeable(mock);
command.runtestmethod();

이제 mymethod(Object o)inside runtestmethod()라고 불리는 Object가 o다른 객체 가 아닌 다른 객체로 호출 되었는지 확인하고 싶습니다 . 그러나 나는 예를 들어 다음과 같이 검증에 넣은 모든 것을 항상 테스트에 통과시킵니다.

Mockito.verify(mock.mymethod(Mockito.eq(obj)));

또는

Mockito.verify(mock.mymethod(Mockito.eq(null)));

또는

Mockito.verify(mock.mymethod(Mockito.eq("something_else")));

나는 항상 시험을 통과합니다. 해당 검증을 어떻게 수행 할 수 있습니까 (가능한 경우)?

감사합니다.



답변

의 대안은 ArgumentMatcher입니다 ArgumentCaptor.

공식 예 :

ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

@Captor 주석을 사용하여 캡터를 정의 할 수도 있습니다 .

@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
    //...
    verify(mock).doSomething(captor.capture());
    assertEquals("John", captor.getValue().getName());
}


답변

객체의 .equals 메소드를 사용하여 논리적 평등을 수행하려고합니까? Mockito에 포함 된 argThat 매처를 사용하여이를 수행 할 수 있습니다.

import static org.mockito.Matchers.argThat

다음으로 각 객체를 연기하는 자체 인수 매처를 구현할 수 있습니다.

private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> {
    T thisObject;

    public ObjectEqualityArgumentMatcher(T thisObject) {
        this.thisObject = thisObject;
    }

    @Override
    public boolean matches(Object argument) {
        return thisObject.equals(argument);
    }
}

이제 코드를 사용하여 읽을 수 있도록 업데이트 할 수 있습니다 …

Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj)).thenReturn(null);

Testeable obj = new Testeable();
obj.setMockeable(mock);
command.runtestmethod();

verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj)));

정확히 같은 평등 (메모리의 동일한 객체)을 원한다면 그냥하십시오.

verify(mock).mymethod(obj);

한 번 호출되었음을 확인합니다.


답변

  • eq다른 매처를 사용하지 않으면 매 처가 필요 하지 않습니다.
  • 올바른 구문을 사용하고 있지 않습니다. 메소드 호출이 외부에 있어야합니다 .verify(mock). 메소드 호출을하지 않고 아무 것도 확인하지 않고 메소드 호출 결과에 대한 검증을 시작했습니다. 따라서 모든 테스트가 통과되었습니다.

코드는 다음과 같아야합니다.

Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");


답변

argThat 람다

이것이 인수 검증에 실패하는 방법입니다.

    verify(mock).mymethod(argThat(
      (x)->false
    ));

어디

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

argThat 더하기 주장

위의 테스트는 “say” Expected: lambda$... Was: YourClass.toSting...입니다. 람다에서 어설 션을 사용하면 더 구체적인 실패 원인을 얻을 수 있습니다.

    verify(mock).mymethod(argThat( x -> {
      assertThat(x).isNotNull();
      assertThat(x.description).contains("KEY");
      return true;
    }));

그러나이 방법은 1 가지 방법으로 만 작동합니다. 확인 된 메소드가 2 번 이상 호출되면 mockito는 모든 호출 된 조합을 각 검증기로 전달합니다. 따라서 mockito는 검증자가 true인수 세트 중 하나에 대해 자동으로 리턴 false하고 다른 유효한 호출에 대해서는 (어설 션 예외 없음)을 기대합니다. 그 기대는 1 개의 메소드 호출에 문제가되지 않습니다. 단순히 1 번 반환해야합니다.

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;

이제 테스트 결과는 다음과 같습니다 Expected: Obj.description to contain 'KEY'. Was: 'Actual description'.. 참고 : assertJ어설 션을 사용했지만 어떤 어설 션 프레임 워크를 사용할지는 사용자에게 달려 있습니다.


argThat 여러 인수로.

을 사용 argThat하면 모든 인수 에 일치 항목이 제공되어야합니다. 예 :

    verify(mock).mymethod(eq("VALUE_1"), argThat((x)->false));
    // above is correct as eq() is also an argument matcher.

verify(mock).mymethod("VALUE_1", argThat((x)->false));

// above is incorrect; an exceptoin will be thrown, as the fist arg. is given without an argument matcher.

어디:

import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;

eq 매처

인수가 같은지 확인하는 가장 쉬운 방법 :

verify(mock).mymethod(eq(expectedValue));
// NOTE:   ^ where the parentheses must be closed.

직접 논증

심판에 의한 비교가 허용되는 경우 다음으로 진행하십시오.

verify(mock).mymethod(expectedArg);
// NOTE:   ^ where the parentheses must be closed.

최초의 질문 실패의 근본 원인은 잘못된 본당의 장소였습니다 verify(mock.mymethod.... 그건 틀렸어 올바른 것은 :verify(mock).*


답변

이런 식으로 Mockito.verify를 사용했습니다.

@UnitTest
public class JUnitServiceTest
{
    @Mock
    private MyCustomService myCustomService;


    @Test
    public void testVerifyMethod()
    {
       Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0))
       Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times
       Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time
       Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times
       Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times
       Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); //   no other method called except this
    }
}


답변

모형 클래스의 equals 메소드를 확인 했습니까? 이 인스턴스가 항상 true를 반환하거나 동일한 인스턴스에 대해 동일한 인스턴스를 테스트하고 동일한 메소드를 덮어 쓰지 않고 (따라서 참조에 대해서만 확인) true를 리턴합니다.


답변

다른 방법은 하나를 재정의하는 대신 org.mockito.internal.matchers.Equals.Equals 방법을 사용하는 것입니다.

verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));