Mockito: simulation d'initialisation privée sur le terrain

comment je peux simuler une variable de champ qui est initialisée en ligne?

e.g.

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

ici je veux me moquer personne.someMethod () en testant la méthode - Test#testMethod.

pour lequel je dois simuler l'initialisation de la variable personne. Aucun indice?

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

36
demandé sur ROMANIA_engineer 2016-03-23 12:14:16

5 réponses

Mockito vient avec une classe helper pour vous sauver un peu de réflexion code de la plaque de la chaudière:

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 mockito a décidé de supprimer la classe dans Mockito 2. Donc vous êtes de retour à écrire votre propre code de boilerplate réflexion, utilisez une autre bibliothèque (par exemple Apache Commons Lang), ou tout simplement piller l' Whitebox classe (c'est sous licence MIT).

58
répondu Ralf 2017-01-16 09:53:51

j'ai déjà trouvé la solution à ce problème dont 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. en cours d'Exécution de mon 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 en dérision le constructeur de la classe Personne:

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

12
répondu Arun 2018-08-23 21:37:32

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

Mockito vient avec ça org.mockito.internal.util.reflection.FieldSetter.

ce qu'il fait essentiellement est vous aide à modifier les champs privés en utilisant la réflexion.

C'est la façon dont 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 simulé et ensuite le vérifier tard.

Référence:

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

2
répondu Raj Kumar 2018-08-21 04:40:58

peut être de plusieurs façons, L'une d'elles peut être

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

Ce doit être modifié comme

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

}

Dans votre test,

@Runwith(SpringJunit4Runner.class)
public class TestingTest {

@InjectMocks
Test test;

@Mock
private Person person;

@Before
public void setUp() {

when(person.XXX).thenReturn("");

}

@Test
public void testMethod() {

...........
}
}
0
répondu VinayVeluri 2016-03-23 09:36:55

le code suivant peut être utilisé pour initialiser mapper dans REST client mock. mapper le champ est privé et doit être réglé lors de la configuration d'essai de l'unité.

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

new FieldSetter(client, Client.class.getDeclaredField("mapper")).set(new Mapper());
0
répondu Jarda Pavlíček 2018-08-22 05:39:08