Mockito: doAnswer Vs thenReturn


125

Mockito'yu daha sonra servis birimi testi için kullanıyorum. Ne zaman kullanılacağını ben karıştı doAnswervs thenReturn.

Biri bana detaylı olarak yardım edebilir mi? Şimdiye kadar denedim thenReturn.

Yanıtlar:


167

Bir yöntem çağrısıyla taklit ettiğiniz anda thenReturnveya doReturndönüş değerini bildiğiniz zaman kullanmalısınız . Bu tanımlanmış değer, sahte yöntemi çağırdığınızda döndürülür.

thenReturn(T value) Yöntem çağrıldığında döndürülecek bir dönüş değeri ayarlar.

@Test
public void test_return() throws Exception {
    Dummy dummy = mock(Dummy.class);
    int returnValue = 5;

    // choose your preferred way
    when(dummy.stringLength("dummy")).thenReturn(returnValue);
    doReturn(returnValue).when(dummy).stringLength("dummy");
}

Answer alay edilen bir yöntem çağrıldığında ek eylemler yapmanız gerektiğinde, örneğin bu yöntem çağrısının parametrelerine göre dönüş değerini hesaplamanız gerektiğinde kullanılır.

doAnswer()Bir void yöntemini jenerik ile belirlemek istediğinizde kullanın Answer.

Cevap, sahte ile etkileşim kurduğunuzda yürütülen bir eylemi ve döndürülen bir dönüş değerini belirtir.

@Test
public void test_answer() throws Exception {
    Dummy dummy = mock(Dummy.class);
    Answer<Integer> answer = new Answer<Integer>() {
        public Integer answer(InvocationOnMock invocation) throws Throwable {
            String string = invocation.getArgumentAt(0, String.class);
            return string.length() * 2;
        }
    };

    // choose your preferred way
    when(dummy.stringLength("dummy")).thenAnswer(answer);
    doAnswer(answer).when(dummy).stringLength("dummy");
}

merhaba @Roland Weisleder ama bazen bir değer üretilen iç kod döndürmelisiniz ve argümanlarla hiçbir ilgisi yoktur, örneğin code = UUID.randomUUID(), bunu uygulamak imkansız buldum mockito.
zhuguowei

3
Modeliniz her çağrı için yeni bir UUID döndürmesi gerektiğinde, Answersadece return UUID.randomUUID();.
Roland Weisleder

Bu yöntemi, kodu biraz daha temiz hale getirmek için yeni Cevap başlatma karınca yönteminden alabilir miyim?
Satır

3
@Line Answerişlevsel bir arayüzdür, bu nedenle Java 8 ile onu bir lambda ifadesiyle değiştirebilirsiniz. Yeterince temiz değilse, başka herhangi bir olağan ve olağandışı yeniden düzenleme mümkündür.
Roland Weisleder

@ zhuguowei: üretilen iç kodun bir kısmını döndürür mü? Bununla ne demek istiyorsun?
Saurabh Patil

35

doAnswerve thenReturnaşağıdaki durumlarda aynı şeyi yapın:

  1. Spy kullanıyorsunuz, Mock kullanıyorsunuz
  2. Stubing yaptığınız yöntem, bir void yöntemi değil, bir değer döndürmektir.

Bu BookService ile alay edelim

public interface BookService {
    String getAuthor();
    void queryBookTitle(BookServiceCallback callback);
}

GetAuthor () 'u doAnswerve kullanarak saplayabilirsiniz thenReturn.

BookService service = mock(BookService.class);
when(service.getAuthor()).thenReturn("Joshua");
// or..
doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        return "Joshua";
    }
}).when(service).getAuthor();

Kullanırken doAnswer, bir yöntemi geçiremeyeceğinizi unutmayın when.

// Will throw UnfinishedStubbingException
doAnswer(invocation -> "Joshua").when(service.getAuthor());

Peki doAnsweryerine ne zaman kullanacaksınız thenReturn? İki kullanım durumu düşünebilirim:

  1. Geçersiz yöntemi "saplamak" istediğinizde.

DoAnswer'ı kullanarak, yöntem çağrısı üzerine bazı ek eylemler yapabilirsiniz. Örneğin, queryBookTitle'da bir geri aramayı tetikleyin.

BookServiceCallback callback = new BookServiceCallback() {
    @Override
    public void onSuccess(String bookTitle) {
        assertEquals("Effective Java", bookTitle);
    }
};
doAnswer(new Answer() {
    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {
        BookServiceCallback callback = (BookServiceCallback) invocation.getArguments()[0];
        callback.onSuccess("Effective Java");
        // return null because queryBookTitle is void
        return null;
    }
}).when(service).queryBookTitle(callback);
service.queryBookTitle(callback);
  1. Mock yerine Spy kullandığınızda

When-then kullanılırken Spy Mockito, gerçek yöntemi çağıracak ve ardından yanıtınızı belirleyecektir. Bu örnekte olduğu gibi gerçek yöntemi çağırmak istemiyorsanız bu bir soruna neden olabilir:

List list = new LinkedList();
List spy = spy(list);
// Will throw java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
when(spy.get(0)).thenReturn("java");
assertEquals("java", spy.get(0));

DoAnswer'ı kullanarak güvenli bir şekilde saplayabiliriz.

List list = new LinkedList();
List spy = spy(list);
doAnswer(invocation -> "java").when(spy).get(0);
assertEquals("java", spy.get(0));

Aslında, yöntem çağrısı üzerine ek eylemler yapmak istemiyorsanız, sadece kullanabilirsiniz doReturn.

List list = new LinkedList();
List spy = spy(list);
doReturn("java").when(spy).get(0);
assertEquals("java", spy.get(0));

Ya alay edilen yöntem geçersizse?
Igor Donin

1
Igor, doAnswer () tam olarak burada devreye giriyor ve bunu yukarıdaki yanıtta ele aldı.
Saurabh Patil

doAnswer(new Answer() { ... return null;}Tutulma sırasında kullandığım zaman "Cevap ham bir tiptir. Jenerik tipe referanslar Cevap <T> parametreleştirilmelidir" şeklinde bir uyarı alıyorum. Bunu çözmenin bir yolu var mı (c uyarısını görmezden gelmek dışında)?
LazR
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.