web-dev-qa-db-fra.com

Comment se moquer d'un constructeur avec mockito

J'ai un constructeur:

class Builder{
     private String name;
     private String address;
     public Builder setName(String name){
         this.name = name;
         return this;
    }
     public Builder setAddress(String address){
         this.address = address;
         return this;
    }

}

Se moquer du constructeur dans mockito me donnera la valeur null pour chaque méthode. Existe-t-il donc un moyen simple pour que le générateur se retourne à chaque appel de fonction, sans se moquer de chaque fonction elle-même en utilisant when().thenReturn.

29
Andreas Köberle

Vous pouvez utiliser RETURN_DEEP_STUBS pour simuler une API de chaînage.

Si vous connaissez l'ordre exact de votre constructeur sera appelé, voici un exemple de la façon dont vous l'utiliseriez:

Builder b = Mockito.mock(Builder.class, RETURNS_DEEP_STUBS);
when(b.setName("a name").setAddress("an address")).thenReturn(b);
assert b.setName("a name").setAddress("an address") == b; // this passes

Malheureusement, cela ne vous donnera pas une manière générique de se moquer de "toutes les différentes méthodes de construction" afin qu'elles retournent toujours ceci, voyez l'autre réponse si vous en avez besoin.

10
Mairbek Khadikov

Le problème avec l'utilisation de RETURN_DEEP_STUBS est que vous obtiendrez une maquette différente chaque fois que vous appelez une méthode. Je pense que d'après votre question, vous souhaitez utiliser une réponse par défaut qui renvoie en fait la maquette sur laquelle elle a été appelée, pour chaque méthode qui a le bon type de retour. Cela pourrait ressembler à ce qui suit. Notez que je n'ai pas testé cela, donc il peut contenir des fautes de frappe, mais j'espère que l'intention est claire dans tous les cas.

import static org.mockito.Mockito.RETURNS_DEFAULTS;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

public class SelfReturningAnswer implements Answer<Object>{

    public Object answer(InvocationOnMock invocation) throws Throwable {
        Object mock = invocation.getMock();
        if( invocation.getMethod().getReturnType().isInstance( mock )){
            return mock;
        }
        else{
            return RETURNS_DEFAULTS.answer(invocation);
        }
    }
}

Ensuite, lorsque vous créez votre maquette, spécifiez cela comme votre réponse par défaut. Cela fera que votre maquette se retournera de chaque méthode qu'elle peut; mais il se comportera comme une maquette ordinaire lorsque vous appelez une méthode dont le type de retour est incorrect pour la maquette.

Créez votre maquette comme ça

Builder mockBuilder = mock( Builder.class, new SelfReturningAnswer());

ou créer une constante pour cette classe et écrire quelque chose comme

@Mock( answer = SELF_RETURNING ) private Builder mockBuilder;

J'espère que cela pourra aider.

41
Dawood ibn Kareem

Depuis Mockito 2.0 (beta), il existe une nouvelle réponse par défaut pour RETURNS_SELF qui se comporte presque de la même manière que réponse de David Wallace . Exemple tiré des documents Mockito:

@Test
public void use_full_builder_with_terminating_method() {
    HttpBuilder builder = mock(HttpBuilder.class, RETURNS_SELF);
    HttpRequesterWithHeaders requester = new HttpRequesterWithHeaders(builder);
    String response = "StatusCode: 200";

    when(builder.request()).thenReturn(response);

    assertThat(requester.request("URI")).isEqualTo(response);
}

Notez qu'il apparaît à la fois sur la classe Mockito et sur l'énumération Answers, il est donc également compatible avec la syntaxe @Mock(answer = RETURNS_SELF).

20
Jeff Bowman