Mockito'nun argümanı örneği


141

Herkes bana org.mockito.ArgumentCaptorsınıfın nasıl kullanılacağını ve mockito ile sağlanan basit eşleştiricilerden nasıl farklı olduğunu gösteren bir örnek verebilir mi?

Verilen mockito belgelerini okudum ama bunlar açıkça göstermiyor, hiçbiri bunu net bir şekilde açıklayamıyor.

Yanıtlar:


187

@Fge'nin söylediklerine katılıyorum, daha fazlası. Örnek olarak bakalım. Bir yönteminiz olduğunu düşünün:

class A {
    public void foo(OtherClass other) {
        SomeData data = new SomeData("Some inner data");
        other.doSomething(data);
    }
}

Şimdi iç verileri kontrol etmek isterseniz, esir kullanabilirsiniz:

// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);

// Run the foo method with the mock
new A().foo(other);

// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());

// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);

Eğer doSomething(data)mutasyon innerData, bu değişikliğin mevcut olacaktır assertEquals("Some inner data", actual.innerData), ya da olacak innerDatagibi-yakalanabilir önce doSomething yürütülür?
Cory Klein

@CoryKlein Bir alaydır OtherClassve şimdi tanımlandığı gibi, doSomething()aslında hiçbir şey yapmaz, sadece geçen nesneyi kaydeder. Bu doSomething, yürütülmeden önce olduğu gibi yakalanacağı anlamına gelir .
Slava Shpitalny

3
Gelen verify, times(1)varsayılan değerdir ve göz ardı edilebilir.
Inego

ArgumentCaptor, foo'nun (diğer) yalnızca foo (diğer) çağrısından sonra başlatıldığı için olduğunu nasıl biliyor?
AvramPop

1
@AvramPop bunun sahte nesne olduğunu bilen kişi. Sahte hakkında birçok bilgi içerir. Tüm bu bilgilerin içinde, parametreleriyle birlikte her bir yöntemin çağrı geçmişini de içerir. verifyYöntemi çağırdığınızda, yaptığınız doğrulama ile eşleşmeleri çalıştırmak için bu bilgileri kullanır. Her parametre için kontrol ettiği belirli çağrı ile eşleşip eşleşmediğini sorar. ArgumentCaptor işaretlendiğinde, çağrıldığı değerleri basitçe depolar, böylece verifysona erdiğinde ilgili tüm çağrıları tutar. Kabaca böyle çalışır. Umut etmek o yardım etmek
Slava Shpitalny

35

İki temel fark şunlardır:

  • tek bir argümanı bile yakaladığınızda, bu argüman üzerinde ve daha açık bir kodla çok daha ayrıntılı testler yapabilirsiniz;
  • bir defadan fazlaArgumentCaptor yakalayabilir .

İkincisini göstermek için, sahip olduğunuzu varsayalım:

final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);

verify(x, times(4)).someMethod(captor.capture()); // for instance

Ardından, esir size daha sonra ayrı ayrı iddialarda bulunabileceğiniz 4 argümanın tümüne erişebilecektir.

Bu veya aslında herhangi bir sayıda argüman, çünkü VerificationModea sabit sayıda çağrı ile sınırlı değildir; her halükarda, esir isterseniz dilerseniz hepsine erişebileceksiniz.

Bu, aynı zamanda, bu tür testlerin yazılmasını (imho) kendi ArgumentMatchers'inizi uygulamaktan çok daha kolay olmasıdır - özellikle mockito'yu assertj ile birleştirirseniz.

Oh, ve lütfen JUnit yerine TestNG kullanmayı düşünün.


1
Yönteme iletilen birden fazla parametre varsa - hepsi farklı türlerde? Örneğin, boolean parametresinin doğru olduğunu nasıl doğrularsınız ?
IgorGanapolsky

21
Yorumunuz için bir açıklama yapabilir misiniz: Oh, ve lütfen JUnit yerine TestNG kullanmayı düşünün. . Neden düşünelim? Neden değişiyorsun?
Navigatron

1
@IgorGanapolsky başka bir ArgumentCaptor ekleyin. ArgumentCaptor <BigDecimal> arg = ArgumentCaptor.forClass (BigDecimal.class); ArgumentCaptor <String> arg2 = ArgumentCaptor.forClass (String.class); Michael michael = yeni Michael (); michael.sayHi (j) verify (j) .saySomething (arg.capture (), arg2.capture ()); System.out.println ("değer" + arg.getValue ()); System.out.println ("dize" + arg2.getValue ());
johnwick0831

12

Tam kontrol yapmak için gereken adımlar şunlardır:

Esir hazırlayın:

ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);

bileşene (test edilen öznenin ortak çalışanı) sürelerine (1) bağlı çağrının varsayılan değer olduğunu doğrulayın, bu yüzden eklemeye gerek yoktur.

verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());

Argümanı ortak çalışana aktarın

SomeArgumentClass someArgument = messageCaptor.getValue();

someArgument, iddialar için kullanılabilir


-2

Burada size bir geri arama yönteminin uygun bir örneğini veriyorum. yani yöntem login () gibi bir yöntemimiz olduğunu varsayalım:

 public void login() {
    loginService = new LoginService();
    loginService.login(loginProvider, new LoginListener() {
        @Override
        public void onLoginSuccess() {
            loginService.getresult(true);
        }

        @Override
        public void onLoginFaliure() {
            loginService.getresult(false);

        }
    });
    System.out.print("@@##### get called");
}

Ayrıca örneği daha açık hale getirmek için tüm yardımcı sınıfı buraya koydum: loginService class

public class LoginService implements Login.getresult{
public void login(LoginProvider loginProvider,LoginListener callback){

    String username  = loginProvider.getUsername();
    String pwd  = loginProvider.getPassword();
    if(username != null && pwd != null){
        callback.onLoginSuccess();
    }else{
        callback.onLoginFaliure();
    }

}

@Override
public void getresult(boolean value) {
    System.out.print("login success"+value);
}}

ve biz de ListListener dinleyicimiz var:

interface LoginListener {
void onLoginSuccess();

void onLoginFaliure();

}

şimdi sadece Login yönteminin login () yöntemini test etmek istedim

 @Test
public void loginTest() throws Exception {
    LoginService service = mock(LoginService.class);
    LoginProvider provider = mock(LoginProvider.class);
    whenNew(LoginProvider.class).withNoArguments().thenReturn(provider);
    whenNew(LoginService.class).withNoArguments().thenReturn(service);
    when(provider.getPassword()).thenReturn("pwd");
    when(provider.getUsername()).thenReturn("username");
    login.getLoginDetail("username","password");

    verify(provider).setPassword("password");
    verify(provider).setUsername("username");

    verify(service).login(eq(provider),captor.capture());

    LoginListener listener = captor.getValue();

    listener.onLoginSuccess();

    verify(service).getresult(true);

ayrıca test sınıfının üzerine ek açıklama eklemeyi unutmayın

@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)

1
ArgumentCaptor'a atıfta bulunmamalı mı?
Felipe Martins Melo

Evet biz örnek giriş yöntemi giriş geçirilen dinleyici () yakalarken (LoginProvider loginProvider, LoginListener geri arama)
Singh Vikram

captorCevabınızdaki tanım nerede ?
tom_mai78101

ArgumentCaptor <LoginListener> listenerCaptor = ArgumentCaptor.forClass (LoginListener.class);
Vikram singh
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.