web-dev-qa-db-fra.com

Mockito: comment stub getter setter

Je suis un peu nouveau pour Mockito et je me demandais comment je pourrais remplacer une paire get/set.

Par exemple

public interface Dummy {
     public String getString();
     public void setString(String string);
}

Comment puis-je les faire se comporter correctement: si quelque part dans un test j'invoque setString("something");, j'aimerais que getString() renvoie "quelque chose". Est-ce faisable ou existe-t-il une meilleure façon de traiter de tels cas?

22
Guillaume Polet

Je voulais aussi que le getter retourne le résultat du dernier appel de setter.

Ayant

class Dog
{
    private Sound sound;

    public Sound getSound() {
        return sound;
    }
    public void setSound(Sound sound)   {
        this.sound = sound;
    }
}

class Sound
{
    private String syllable;

    Sound(String syllable)  {
        this.syllable = syllable;
    }
}

J'ai utilisé ce qui suit pour connecter le passeur au getter:

final Dog mockedDog = Mockito.mock(Dog.class, Mockito.RETURNS_DEEP_STUBS);
// connect getter and setter
Mockito.when(mockedDog.getSound()).thenCallRealMethod();
Mockito.doCallRealMethod().when(mockedDog).setSound(Mockito.any(Sound.class));
30
user2006754

Je peux penser à trois approches possibles.

  1. N'utilisez pas HttpServletRequest directement dans votre application; faire une classe wrapper pour elle et avoir une interface pour la classe wrapper. Où que vous utilisiez actuellement HttpServletRequest dans l'application, utilisez plutôt l'interface. Ensuite, dans le test, ayez une implémentation alternative de cette interface. Ensuite, vous n'avez pas besoin d'une maquette Mockito.

  2. Ayez un champ dans votre classe de test qui stocke la valeur que vous avez définie à String. Créez deux objets Mockito Answer; un qui retourne la valeur de ce champ lorsque getString est appelé, et un autre qui en définit la valeur lorsque setString est appelé. Faites une maquette de la manière habituelle, et utilisez les deux réponses suivantes.

  3. Créez une classe abstraite (qui peut être une classe interne statique de votre classe de test) qui implémente l'interface HttpServletRequest, mais qui possède le champ que vous souhaitez définir, et définit les méthodes de lecture et de définition. Puis moquez la classe abstraite et transmettez Mockito.CALLS_REAL_METHODS comme réponse par défaut. Lorsque vous appelez le getter ou le passeur de la maquette, la vraie méthode entre en jeu, à savoir le comportement que vous souhaitez. 

Espérons qu'une de ces trois solutions répondra à vos besoins.

6
Dawood ibn Kareem

J'avais ce problème, mais je ne voulais pas accepter la réponse acceptée, car cela mettrait fin à la moquerie de tous getters et setters dans ma fève. Tout ce que je voulais, c'était créer des talons pour un seul couple getter/setter, pas tous. En tant que tel, j'ai utilisé le code suivant.

@Mock
private Dummy mockDummy;
private final MutableObject<String> stringWrapper = new MutableObject<>();

public TestClass() {
    MockitoAnnotations.initMocks(this);

    doAnswer(invocationOnMock -> {
        String injectedString = (String)invocationOnMock.getArguments()[0];
        TestClass.this.stringWrapper.setValue(injectedString);
        return null;
    }).when(this.mockDummy).setString(any());
    when(this.mockDummy.getString()).thenAnswer(
            invocationOnMock -> TestClass.this.stringValue.getValue());
}

Le premier lambda implémente la méthode Answer<Void> anonymous class ' answer() . Ainsi, chaque fois que la méthode setter est exécutée par le code sous test, ce module de son créateur l'enregistre dans l'objet d'assistance MutableObject . Cette valeur enregistrée qui a été définie peut ensuite être renvoyée par l'implémentation de lecture.

0
entpnerd