Comment faire des méthodes mock to void avec mockito

comment simuler des méthodes avec le type de retour de vide?

j'ai mis en place un modèle D'observateur mais je ne peux pas me moquer avec Mockito parce que je ne sais pas comment.

et j'ai essayé de trouver un exemple sur Internet, mais sans succès.

ma classe ressemble à

public class World {

    List<Listener> listeners;

    void addListener(Listener item) {
        listeners.add(item);
    }

    void doAction(Action goal,Object obj) {
        setState("i received");
        goal.doAction(obj);
        setState("i finished");
    }

    private string state;
    //setter getter state
} 

public class WorldTest implements Listener {

    @Test public void word{
    World  w= mock(World.class);
    w.addListener(this);
    ...
    ...

    }
}

interface Listener {
    void doAction();
}

le système n'est pas déclenché avec mock. =( Je veux montrer l'état du système mentionné ci-dessus. Et faire des affirmations selon eux.

741
demandé sur Janusz 2010-02-16 23:54:39

10 réponses

regardez le Mockito API docs . Comme le document lié le mentionne (Point # 12), Vous pouvez utiliser n'importe lequel des doThrow() , doAnswer() , doNothing() , doReturn() famille de méthodes du cadre de Mockito aux méthodes du vide simulé.

par exemple,

Mockito.doThrow(new Exception()).when(instance).methodName();

ou si vous souhaitez les combiner avec un suivi de comportement,

Mockito.doThrow(new Exception()).doNothing().when(instance).methodName();

présumant que vous regardez se moquer de la setter setState(String s) dans la classe monde ci-dessous est le code utilise doAnswer méthode pour moquer le setState .

World  mockWorld = mock(World.class); 
doAnswer(new Answer<Void>() {
    public Void answer(InvocationOnMock invocation) {
      Object[] args = invocation.getArguments();
      System.out.println("called with arguments: " + Arrays.toString(args));
      return null;
    }
}).when(mockWorld).setState(anyString());
954
répondu sateesh 2017-07-25 03:41:18

je pense que j'ai trouvé une réponse plus simple à cette question, pour appeler la vraie méthode pour une seule méthode (même si elle a un retour de vide) vous pouvez faire ceci:

Mockito.doCallRealMethod().when(<objectInstance>).<method>();
<objectInstance>.<method>();

ou, vous pourriez appeler la vraie méthode pour toutes les méthodes de cette classe, faisant ceci:

<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);
88
répondu MarcioB 2014-06-10 20:41:15

ajoutant à ce que @sateesh a dit, quand vous voulez juste vous moquer d'une méthode de vide afin d'empêcher le test de l'appeler, vous pouvez utiliser un Spy de cette façon:

World world = new World();
World spy = Mockito.spy(world);
Mockito.doNothing().when(spy).methodToMock();

lorsque vous voulez exécuter votre test, assurez-vous d'appeler la méthode en test sur l'objet spy et non sur l'objet world . Par exemple:

assertEquals(0,spy.methodToTestThatShouldReturnZero());
52
répondu Omri374 2015-07-19 12:07:06

la solution du soi-disant problème est d'utiliser un spy Mockito.espion.(..) au lieu d'un mock Mockito.moquer.(.) .

Spy nous permet de nous moquer partiellement. Mockito est bon à ce sujet. Parce que vous avez une classe qui n'est pas complète, de cette façon vous vous moquez d'une place requise dans cette classe.

50
répondu ibrahimyilmaz 2016-10-19 15:47:25

tout D'abord: vous devez toujours importer mockito statique, de cette façon le code sera beaucoup plus lisible (et intuitif):

import static org.mockito.Mockito.*;

pour la moquerie partielle et toujours garder la fonctionnalité originale sur le mockito de repos offre "Espion".

Vous pouvez l'utiliser comme suit:

private World world = spy(World.class);

pour éliminer une méthode d'être exécuté vous pourriez utiliser quelque chose comme ceci:

doNothing().when(someObject).someMethod(anyObject());

pour donner comportement personnalisé à une utilisation de méthode "quand" avec un "thenReturn":

doReturn("something").when(this.world).someMethod(anyObject());

pour plus d'exemples, veuillez trouver les échantillons de mockito dans le doc.

22
répondu fl0w 2016-11-11 16:06:47

comment simuler des méthodes de vide avec mockito - il y a deux options:

  1. doAnswer - si nous voulons que notre méthode du vide moqué fasse quelque chose (moquez le comportement malgré être vide).
  2. doThrow - puis il y a Mockito.doThrow() si vous voulez jeter une exception de la méthode mocked void.

ci-dessous est un exemple de la façon de l'utiliser (pas une usecase idéal, mais juste voulu illustrer l'utilisation de base).

@Test
public void testUpdate() {

    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            Object[] arguments = invocation.getArguments();
            if (arguments != null && arguments.length > 1 && arguments[0] != null && arguments[1] != null) {

                Customer customer = (Customer) arguments[0];
                String email = (String) arguments[1];
                customer.setEmail(email);

            }
            return null;
        }
    }).when(daoMock).updateEmail(any(Customer.class), any(String.class));

    // calling the method under test
    Customer customer = service.changeEmail("old@test.com", "new@test.com");

    //some asserts
    assertThat(customer, is(notNullValue()));
    assertThat(customer.getEmail(), is(equalTo("new@test.com")));

}

@Test(expected = RuntimeException.class)
public void testUpdate_throwsException() {

    doThrow(RuntimeException.class).when(daoMock).updateEmail(any(Customer.class), any(String.class));

    // calling the method under test
    Customer customer = service.changeEmail("old@test.com", "new@test.com");

}
}

vous pourriez trouver plus de détails sur la façon de mock et test nul méthodes avec Mockito dans mon post comment moquer avec Mockito (un guide complet avec des exemples)

18
répondu Dilini Rajapaksha 2017-05-29 02:52:16

ajout d'une autre réponse au groupe (sans jeu de mots)...

vous ne devez appeler la méthode doAnswer si vous ne pouvez pas\don't want to use spy's. Cependant, vous n'avez pas nécessairement besoin de lancer votre propre réponse . Il existe plusieurs implémentations par défaut. Notamment, Appelle Les Méthodes Réelles .

dans la pratique, il ressemble à quelque chose comme ceci:

doAnswer(new CallsRealMethods()).when(mock)
        .voidMethod(any(SomeParamClass.class));

ou:

doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
        .voidMethod(any(SomeParamClass.class));
12
répondu javamonkey79 2014-03-31 12:31:16

je pense que vos problèmes sont dus à votre structure de test. J'ai trouvé difficile de mélanger la moquerie avec la méthode traditionnelle d'implémentation des interfaces dans la classe test (comme vous l'avez fait ici).

si vous implémentez l'auditeur comme une simulation, vous pouvez alors vérifier l'interaction.

Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();

cela devrait vous satisfaire que le "monde" fait la bonne chose.

5
répondu ashley 2014-07-07 07:56:30

en Java 8 cela peut être fait un peu plus propre, en supposant que vous avez une importation statique pour org.mockito.Mockito.doAnswer :

doAnswer(i -> {
  // Do stuff with i.getArguments() here
  return null;
}).when(*mock*).*method*(*methodArguments*);

le return null; est important et sans lui la compilation échouera avec quelques erreurs assez obscures car il ne sera pas en mesure de trouver un contrôleur approprié pour doAnswer .

par exemple, un ExecutorService qui exécute immédiatement n'importe quel Runnable passé à execute() pourrait être mis en œuvre en utilisant:

doAnswer(i -> {
  ((Runnable) i.getArguments()[0]).run();
  return null;
}).when(executor).execute(any());
5
répondu Tim B 2018-09-04 09:43:54

@ashley : fonctionne pour moi

public class AssetChangeListenerImpl extends
AbstractAssetChangeListener implements AssetChangeListener {

  @Override
  public void onChangeEvent(final EventMessage message) throws EventHubClientException {
      execute(message);
    }
  }
}

public class AbstractAssetChangeListener {
  protected  void execute( final EventMessage message ) throws EventHubClientException {
    executor.execute( new PublishTask(getClient(), message) );
} } @RunWith(MockitoJUnitRunner.class) public class AssetChangeListenerTest extends AbstractAssetChangeListenerTest {

 public void testExecute() throws EventHubClientException {
    EventMessage message = createEventMesage(EventType.CREATE);
    assetChangeListener.execute(message);
    verify(assetChangeListener, times(1)).execute(message);
} }
0
répondu Yoga Gowda 2017-04-21 11:15:56