İlk aramayı simüle etme başarısız, ikinci arama başarılı


119

Aşağıdaki (basitleştirilmiş) kodu test etmek için Mockito kullanmak istiyorum. Mockito'ya ilk seferde başarısız olmasını, sonra ikinci seferde başarılı olmasını nasıl söyleyeceğimi bilmiyorum.

for(int i = 1; i < 3; i++) {
  String ret = myMock.doTheCall();

  if("Success".equals(ret)) {
    log.write("success");
  } else if ( i < 3 ) {
    log.write("failed, but I'll try again. attempt: " + i);
  } else {
    throw new FailedThreeTimesException();
  }
}

Başarı testini şu şekilde kurabilirim:

Mockito.when(myMock).doTheCall().thenReturn("Success");

Ve başarısızlık testi:

Mockito.when(myMock).doTheCall().thenReturn("you failed");

Ama bir (veya iki kez) başarısız olursa başarılı olup olmadığını nasıl test edebilirim?

Yanıtlar:


250

Gönderen docs :

Bazen aynı yöntem çağrısı için farklı dönüş değeri / istisnası ile saplama yapmamız gerekir. Tipik kullanım durumu, alaycı yineleyiciler olabilir. Mockito'nun orijinal sürümü, basit alay etmeyi teşvik etmek için bu özelliğe sahip değildi. Örneğin, yineleyiciler yerine yinelenebilir veya yalnızca koleksiyonlar kullanılabilir. Bunlar doğal saplama yolları sunar (örneğin, gerçek koleksiyonlar kullanmak). Nadir durumlarda, ardışık çağrıları tekrarlamak yararlı olabilir, ancak:

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
  .thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

Yani senin durumunda şunu isteyeceksin:

when(myMock.doTheCall())
   .thenReturn("You failed")
   .thenReturn("Success");

25
Bu, geçersiz yöntemlerle uğraşan senaryom için beni doğru yöne işaret etti (teşekkürler) - bu durumda alternatif stili kullanmanız gerekir ...doThrow(new RuntimeException()).doNothing().when(myMock).doTheCall();
haggisandchips

38

İstediğinizi yazmanın en kısa yolu

when(myMock.doTheCall()).thenReturn("Success", "you failed");

Bunu thenReturnbeğenmek için birden fazla argüman sağladığınızda , her argüman, gerektiği kadar çok kullanılan son argüman haricinde en fazla bir kez kullanılacaktır. Örneğin, bu durumda, aramayı 4 kez yaparsanız, "Başarılı", "başarısız oldunuz", "başarısız oldunuz", "başarısız oldunuz" alırsınız.


22

Bununla ilgili yorumu okumak zor olduğundan, formatlanmış bir cevap ekleyeceğim.

Bunu voidsadece bir istisna atan bir işlevle yapmaya çalışıyorsanız , ardından davranışsız bir adım izlerseniz, şuna benzer bir şey yaparsınız:

Mockito.doThrow(new Exception("MESSAGE"))
            .doNothing()
            .when(mockService).method(eq());

4

Üzerine eklemek için bu ve bu cevap, ayrıca zincire alay çağrıları bir döngü kullanabilirsiniz. Bu, aynı şeyle birkaç kez dalga geçmeniz veya bir düzen içinde alay etmeniz gerekiyorsa kullanışlıdır.

Örneğin (çok zor olsa da):

import org.mockito.stubbing.Stubber;

Stubber stubber = doThrow(new Exception("Exception!"));
for (int i=0; i<10; i++) {
    if (i%2 == 0) {
        stubber.doNothing();
    } else {
        stubber.doThrow(new Exception("Exception"));
    }
}
stubber.when(myMockObject).someMethod(anyString());

Aslında bu Stubber'ı bilmiyordum ve faydalı buldum +1.
Mihai Morcov

Bir void yöntemine ihtiyacınız varsa, bu doğru cevap olmalıdır.
db80

4

Farklı bir durumum var, voidilk arama için bir işlevle alay etmek ve ikinci aramada normal şekilde çalıştırmak istedim .

Bu benim için çalışıyor:

Mockito.doThrow(new RuntimeException("random runtime exception"))
       .doCallRealMethod()
       .when(spy).someMethod(Mockito.any());
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.