web-dev-qa-db-fra.com

Mockito: doAnswer Vs thenReturn

J'utilise Mockito pour le service après-vente des tests unitaires. Je suis confus quand utiliser doAnswer vs thenReturn.

Quelqu'un peut-il m'aider en détail? Jusqu'ici, je l'ai essayé avec thenReturn.

86
Rajkumar Thambu

Vous devez utiliser thenReturn ou doReturn lorsque vous connaissez la valeur de retour au moment où vous vous moquez d'un appel de méthode. Cette valeur définie est renvoyée lorsque vous appelez la méthode simulée.

thenReturn(T value) Définit une valeur de retour à renvoyer lorsque la méthode est appelée.

@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 est utilisé lorsque vous devez effectuer des actions supplémentaires lorsqu'une méthode simulée est appelée, par exemple. lorsque vous devez calculer la valeur de retour en fonction des paramètres de cet appel de méthode.

Utilisez doAnswer() lorsque vous souhaitez remplacer une méthode void avec le générique Answer.

La réponse spécifie une action qui est exécutée et une valeur de retour qui est renvoyée lorsque vous interagissez avec le mock.

@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");
}
123
Roland Weisleder

doAnswer et thenReturn font la même chose si:

  1. Vous utilisez Mock, pas Spy
  2. La méthode que vous remplacez renvoie une valeur, pas une méthode vide.

Raillons ce BookService

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

Vous pouvez bloquer getAuthor () en utilisant doAnswer et 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();

Notez que lorsque vous utilisez doAnswer, vous ne pouvez pas transmettre de méthode à when.

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

Alors, quand utiliseriez-vous doAnswer au lieu de thenReturn? Je peux penser à deux cas d'utilisation:

  1. Lorsque vous voulez "stub" méthode void.

En utilisant doAnswer, vous pouvez effectuer certaines actions supplémentaires lors de l’appel de la méthode. Par exemple, déclencher un rappel sur queryBookTitle.

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. Lorsque vous utilisez Spy au lieu de Mock

Lors de l’utilisation de when-thenReturn on, Spy Mockito appellera méthode réelle puis stub votre réponse. Cela peut poser un problème si vous ne souhaitez pas appeler une méthode réelle, comme dans cet exemple:

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

En utilisant doAnswer, nous pouvons le remplacer en toute sécurité.

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

En fait, si vous ne souhaitez pas effectuer d'actions supplémentaires lors de l'appel de la méthode, vous pouvez simplement utiliser doReturn.

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