모키 토. 메소드 인수 확인


220

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

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")));

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

감사합니다.

답변:


334

의 대안은 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());
}

1
샘플 주셔서 감사합니다! 사용하지 마십시오. 코드에서 captor 와 같은 것을 갖는 것이 약간 이상 하다고 생각하지만 도움이되었습니다.
Artemis

1
하하, 나는 그 질문을 이해하지 못했지만 그 대답은 많은 도움이되었습니다. 감사합니다 :-)
Marcus K.

13
중요 사항 : mock 사용한 verify () / capture ()를 호출 하십시오. 나는 ... 그 전에 "설치"해야합니다 생각
다니엘 알더

1
이 답변에 감사드립니다!
Jose Flavio Quispe Irrazábal

이것은 좋은 대답입니다! 대단히 감사합니다!
울키 Igor

61

객체의 .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);

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


1
ReflectionEquals그 목적으로 클래스 에서 빌드를 사용할 수 있습니다 .
takacsot

2
답변을 +1하십시오. 그러나 verify(mock).mymethod(obj);정확한 동등성을 확인하지 않는 추가하고 싶습니다 (메모리의 동일한 객체). 대신 덮어 쓸 수있는 equals-method 객체를 사용합니다.
efux

ArgumentMatcher덜 장황한 익명 구현을 만들 수도 있습니다 .
botchniaque

1
세부 사항 : 기본적으로 / recorded 오브젝트의 / 메소드 대신 verify()/ inbound 인수의 / equals()메소드를 호출합니다 equals(). 테스트 대상이 특정 객체 인스턴스를 반환하는지 확인하려고 시도하지 않고 대상이 해당 인스턴스의 투명한 데코레이터 인 것을 반환하지 않는 한 이는 관련이 없습니다. verify인수의는 equals()데코레이터의 모르겠다; 데코레이터 equals()는 원본을 허용하도록 다시 작성됩니다. 이 경우 테스트가 잘못 실패합니다.
Mark McKenna

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

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

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

나는 그것을 전에, 그리고 지금 다시 시도했다. 나는 여전히 똑같은 문제가 있으며 테스트는 항상 통과합니다.
manolowar

2
그것은 참조로
verifeis

17

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).*


1
이것은 내가 가장 좋아하는 대답이며 다른 것보다 훨씬 우아합니다.
Airwavezx

11

이런 식으로 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
    }
}

5

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


4

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

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

3

같은 () 매 처로 사용해 보셨습니까? 에서처럼 :

verify(mockObj).someMethod(same(specificInstance));

나는 같은 문제가 있었다. eq () 매처와 refEq () 매 처로 시도했지만 항상 잘못된 긍정을 가졌습니다. same () 매처를 사용할 때 인수가 다른 인스턴스 일 때 테스트가 실패하고 인수가 동일한 인스턴스 인 경우 전달되었습니다.


-1

TypeSafeDiagnosingMatcher를 사용할 수도 있습니다

    private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) {
    return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() {

        StringBuilder text = new StringBuilder(500);

        @Override
        protected boolean matchesSafely(GetPackagesRequest req, Description desc) {
            String productCode = req.getPackageIds().iterator().next().getValue();
            if (productCode.equals(request.getSupplierProductCode())) {
                text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode());
                return true;
            }

            text.append(req.toString());
            return false;
        }

        @Override
        public void describeTo(Description d) {
            d.appendText(text.toString());
        }
    };
}

그런 다음 호출을 확인하십시오.

Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.