Mockito. Yöntem bağımsız değişkenlerini doğrulama


220

Ben bu konuda googled, ama ilgili bir şey bulamadık. Böyle bir şey var:

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

Şimdi, mymethod(Object o)içeride runtestmethod()denilen o, başkalarıyla değil , Object ile çağrıldığını doğrulamak istiyorum . Ama her zaman testi geçiyorum, doğrulamada ne yaparsam yapayım, örneğin:

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

veya

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

veya

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

Her zaman testi geçiyorum. Bu doğrulamayı nasıl yapabilirim (mümkünse)?

Teşekkür ederim.

Yanıtlar:


334

Bir alternatif ArgumentMatcherolduğunu ArgumentCaptor.

Resmi örnek:

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

Bir esir ayrıca @Captor ek açıklaması kullanılarak da tanımlanabilir :

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

1
Örnek için teşekkürler! Hiç kullanmadı. Kodda esir gibi şeylere sahip olmak biraz garip geliyor , ama yardımcı oldu.
Artemis

1
Haha, soruyu anlamadım, ama cevap bana çok yardımcı oldu. Teşekkürler :-)
Marcus K.

13
Önemli: Sahte kullandıktan sonra verify () / capture () yöntemini çağırın . Daha önce "kurulması" gerektiğini düşünüyordum ...
Daniel Alder

1
Bu cevap için teşekkürler!
Jose Flavio Quispe Irrazábal

Bu harika bir cevap! Çok teşekkür ederim!
Ulky Igor

61

Nesnenin .equals yöntemini kullanarak mantıksal eşitlik yapmaya mı çalışıyorsunuz? Mockito'da bulunan argThat eşleştiricisini kullanarak bunu yapabilirsiniz

import static org.mockito.Matchers.argThat

Daha sonra, her nesneye erteleyecek kendi bağımsız değişken eşleştiricinizi uygulayabilirsiniz .equals yöntemi

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

Şimdi kodunuzu kullanarak okumak için güncelleyebilirsiniz ...

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

Sadece EXACT eşitliği (hafızadaki aynı nesne) için gidiyorsanız,

verify(mock).mymethod(obj);

Bu, bir kez çağrıldığını doğrular.


1
Bu ReflectionEqualsamaçla sınıfta derlemeyi kullanabilirsiniz .
takacsot

2
Cevabınız için +1. Ama şunu eklemek isterim ki verify(mock).mymethod(obj);EXACT eşitliğini kontrol etmiyor (bellekteki aynı nesne). Bunun yerine, üzerine yazılabilen equals-method nesnelerini kullanır.
efux

Daha ArgumentMatcheraz ayrıntılı olması için anonim bir uygulama da oluşturabilirsiniz .
botchniaque

1
Daha fazla ayrıntı: varsayılan olarak / kaydedilen nesnenin / yöntemi yerine verify()/ gelen bağımsız değişkeninin / equals()yöntemini çağırır equals(). test konunuzun belirli bir nesne örneği döndürdüğünü ve öznenin bunun yerine bu örneğin şeffaf bir dekoratörü olması gereken şeyi döndürdüğünü doğrulamaya çalışmadığınız sürece bu önemsizdir. verifyArgüman en equals()dekoratör bilemeyiz; dekoratör equals()orijinali tolere etmek için yeniden yazılır. Bu durumda testiniz hatalı olarak başarısız olur.
Mark McKenna

54
  • Başka eqeşleştiriciler kullanmıyorsanız eşleştiriciye ihtiyacınız yoktur.
  • Doğru sözdizimini kullanmıyorsunuz - yöntem çağrınızın .verify(mock). Artık yöntem çağrısının sonucunu, hiçbir şeyi doğrulamadan (yöntem çağrısı yapmadan) doğrulamaya başlıyorsunuz. Böylece tüm testler geçiyor.

Kodunuz şöyle görünmelidir:

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

Bunu daha önce denedim ve şimdi emin olmak için tekrar. Hala aynı problemim var, test her zaman geçiyor.
manolowar

2
Referansla
doğrulanır

17

argThat artı lambda

argüman doğrulama işleminizi bu şekilde başaramazsınız:

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

nerede

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

argThat artı ileri sürüyor

yukarıdaki test "söyleyecektir" Expected: lambda$... Was: YourClass.toSting.... Lambda'da ekleri kullanırsanız, başarısızlığın daha spesifik bir nedenini alabilirsiniz:

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

AMA: SADECE 1 YÖNTEM ARAMASI İLE ÇALIŞIR. Doğrulanmış yöntem 2+ kez çağrılırsa, mockito çağrılan tüm kombinasyonları her doğrulayıcıya geçirir. Bu nedenle mockito, doğrulayıcınızın truebağımsız değişken kümelerinden biri için sessizce geri dönmesini ve falsediğer geçerli çağrılar için ( onaylama istisnası yok) beklemesini bekler . Bu beklenti 1 yöntem çağrısı için bir sorun değildir - sadece 1 kez doğru dönmelidir.

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

Şimdi Test diyor: Expected: Obj.description to contain 'KEY'. Was: 'Actual description'. NOT: Ben assertJiddiaları kullandım , ama hangi iddia çerçevesini kullanmak size kalmış.


argThat birden çok argüman ile.

Eğer kullanırsanız argThat, tüm argümanlarla eşleşme sağlanmalıdır. Örneğin:

    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.

nerede:

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

eq eşleştirici

argümanın eşit olup olmadığını kontrol etmenin en kolay yolu:

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

doğrudan tartışma

ref ile karşılaştırma kabul edilebilirse, o zaman devam edin:

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

Orijinal soru başarısızlık KÖK NEDEN paranthes yanlış bir yerdi: verify(mock.mymethod.... Bu yanlıştı. Doğru:verify(mock).*


1
Bu benim en sevdiğim cevap, çalışıyor ve diğerlerinden çok daha zarif.
Airwavezx

11

Mockito.verify'ı bu şekilde kullandım

@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

Alay edilebilir sınıf için eşittir yöntemini kontrol ettiniz mi? Bu her zaman true değerini döndürürse veya aynı örneği aynı örneğe karşı test ederseniz ve eşit yöntemin üzerine yazılmazsa (ve bu nedenle yalnızca başvurulara karşı denetimler), true değerini döndürür.


4

Diğer yöntem, birini yeniden tanımlamak yerine org.mockito.internal.matchers.Equals.Equals yöntemini kullanmaktır:

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

3

Aynı () eşleştiriciyle denediniz mi? De olduğu gibi:

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

Ben de aynı problemi yaşadım. Bunu eq () eşleştiricisi ve refEq () eşleştiricisi ile denedim ama her zaman yanlış pozitiflerim vardı. Aynı () eşleştiricisini kullandığımda, bağımsız değişkenler farklı örnekler olduğunda sınama başarısız oldu ve bağımsız değişkenler aynı örnek olduğunda bir kez geçti.


-1

Ayrıca TypeSafeDiagnosingMatcher'ı da kullanabilirsiniz

    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());
        }
    };
}

Ardından bu çağrıyı doğrulayın:

Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.