web-dev-qa-db-fra.com

Mockito: Mock initialisation de champ privé

Comment puis-je simuler une variable de champ en cours d'initialisation?

par exemple.

class Test {
    private Person person = new Person();
    ...
    public void testMethod() {
        person.someMethod();
        ...
    }
}

Ici, je veux me moquer de person.someMethod () en testant la méthode - Test # testMethod.

pour lequel je dois simuler l’initialisation de la variable personne. Un indice?

EDIT: Je ne suis pas autorisé à modifier la classe Personne.

58
Arun

J'ai déjà trouvé la solution à ce problème que j'ai oublié de poster ici.

@RunWith(PowerMockRunner.class)
@PrepareForTest({ Test.class })
public class SampleTest {

@Mock
Person person;

@Test
public void testPrintName() throws Exception {
    PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);
    Test test= new Test();
    test.testMethod();
    }
}

Les points clés de cette solution sont:

  1. Exécution de mes cas de test avec PowerMockRunner: @RunWith(PowerMockRunner.class)

  2. Demandez à Powermock de préparer Test.class pour la manipulation de champs privés: @PrepareForTest({ Test.class })

  3. Et enfin moquez le constructeur de la classe Person:

    PowerMockito.mockStatic(Person.class);PowerMockito.whenNew(Person.class).withNoArguments().thenReturn(person);

22
Arun

Mockito est livré avec une classe d'assistance pour vous faire économiser un code de plaque de chaudière par réflexion:

import org.mockito.internal.util.reflection.Whitebox;

//...

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    Whitebox.setInternalState(underTest, "person", mockedPerson);
    // ...
}

Mise à jour: Malheureusement, l'équipe de Mockito a décidé de supprimer la classe dans Mockito 2. Vous êtes donc revenu à l'écriture de votre propre passe-partout par réflexion code, utilisez une autre bibliothèque (par exemple Apache Commons Lang ) ou volez simplement la classe Whitebox (il s’agit de licence MIT ).

Mise à jour 2: JUnit 5 est livré avec ses propres classes ReflectionSupport et AnnotationSupport qui pourraient être utiles et vous empêche de tirer dans une autre bibliothèque.

78
Ralf

Assez tard pour la fête, mais j'ai été frappé ici et j'ai eu l'aide d'un ami. La chose n'était pas d'utiliser PowerMock. Cela fonctionne avec la dernière version de Mockito.

Mockito est livré avec ce org.mockito.internal.util.reflection.FieldSetter.

En gros, cela vous aide à modifier les champs privés en utilisant la réflexion.

Voici comment vous l'utilisez -

@Mock
private Person mockedPerson;
private Test underTest;

// ...

@Test
public void testMethod() {
    FieldSetter.setField(underTest, underTest.getClass().getDeclaredField("person"), mockedPerson);
    // ...
    verify(mockedPerson).someMethod();

}

De cette façon, vous pouvez passer un objet fantaisie puis le vérifier plus tard.

Référence:

https://www.codota.com/code/Java/methods/org.mockito.internal.util.reflection.FieldSetter/set

25
Raj Kumar

Si vous utilisez Spring Test, essayez org.springframework.test.util.ReflectionTestUtils

 ReflectionTestUtils.setField(testObject, "person", mockedPerson);
15
Zimbo Rodger

Le code suivant peut être utilisé pour initialiser le mappeur dans le mock client REST. Le champ mapper est privé et doit être défini lors de la configuration du test unitaire.

import org.mockito.internal.util.reflection.FieldSetter;

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
7
Jarda Pavlíček

À l'aide du guide de @ Jarda, vous pouvez définir ceci si vous devez définir la variable avec la même valeur pour tous les tests:

@Before
public void setClientMapper() throws NoSuchFieldException, SecurityException{
    FieldSetter.setField(client, client.getClass().getDeclaredField("mapper"), new Mapper());
}

Mais sachez que la définition de valeurs privées différentes doit être traitée avec précaution. Si elles sont privées le sont pour une raison quelconque.

Par exemple, je l'utilise, par exemple, pour modifier le temps d'attente d'un sommeil dans les tests unitaires. Dans les exemples réels, je veux dormir pendant 10 secondes mais dans le test unitaire, je suis satisfait si c'est immédiat. Dans les tests d'intégration, vous devez tester la valeur réelle.

3
Hugo Dias