Question Comment faire semblant d'annuler des méthodes avec mockito


Comment se moquer des méthodes avec le type de retour vide?

J'ai mis en place un pattern Observer mais je ne peux pas me moquer de Mockito car je ne sais pas comment.

Et j'ai essayé de trouver un exemple sur Internet, mais je n'ai pas réussi.

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 ne sont pas déclenchés avec un faux. = ( Je veux montrer l'état du système mentionné ci-dessus. Et faites l'affirmation selon eux.


721
2018-02-16 20:54


origine


Réponses:


Jetez un oeil à la Mockito Documents d'API. Comme le mentionne le document lié (Point # 12), vous pouvez utiliser l'un des doThrow(),doAnswer(),doNothing(),doReturn() famille de méthodes du framework Mockito aux méthodes de simulation de vide.

Par exemple,

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

ou si vous voulez le combiner avec un comportement de suivi,

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

En supposant que vous cherchez à se moquer du setter setState(String s) dans la classe Monde ci-dessous est le code utilise doAnswer méthode pour se moquer de la 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());

931
2018-02-17 04:02



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 vide), vous pouvez le faire:

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

Ou, vous pouvez appeler la méthode réelle pour toutes les méthodes de cette classe, en faisant ceci:

<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);

84
2018-06-10 20:41



Ajoutant à ce que @sateesh a dit, quand vous voulez juste simuler une méthode void afin d'empêcher le test de l'appeler, vous pouvez utiliser un Spy par ici:

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 le spy objet et non sur le world objet. Par exemple:

assertEquals(0,spy.methodToTestThatShouldReturnZero());

50
2018-01-09 20:08



La solution de ce qu'on appelle le problème est d'utiliser un spy  Mockito.spy (...) au lieu d'un mock  Mockito.mock (..).

Spy nous permet de se 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 de la place requise dans cette classe.


49
2018-02-18 08:48



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 le moqueur partiel et en gardant toujours la fonctionnalité originale sur le reste, Mockito offre "Spy".

Vous pouvez l'utiliser comme suit:

private World world = spy(World.class);

Pour éliminer une méthode d'exécution, vous pouvez utiliser quelque chose comme ceci:

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

pour donner un comportement personnalisé à une méthode, utilisez "when" avec "thenReturn":

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

Pour plus d'exemples, veuillez trouver les échantillons de mockito dans le document.


20
2017-11-11 14:51



Comment se moquer des méthodes void avec mockito - il y a deux options:

  1. doAnswer - Si nous voulons que notre méthode de vide moqué fasse quelque chose (se moquer du comportement en dépit d'être nul).
  2. doThrow - Ensuite il y a Mockito.doThrow() si vous voulez lancer une exception de la méthode mocked void.

Voici un exemple de comment l'utiliser (pas une utilisation idéale, mais je voulais juste 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 moquer et tester  vide méthodes avec Mockito dans mon message Comment se moquer de Mockito (Un guide complet avec des exemples)


16
2018-05-25 00:26



Ajout d'une autre réponse à la grappe (sans jeu de mots) ...

Vous devez appeler la méthode doAnswer si vous ne pouvez pas utiliser d'espionnage. Cependant, vous n'avez pas nécessairement besoin de rouler le vôtre Répondre. Il existe plusieurs implémentations par défaut. Notamment, CallsRealMethods.

En pratique, cela ressemble à ceci:

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

Ou:

doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
        .voidMethod(any(SomeParamClass.class));

12
2018-03-19 17:41



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

Si vous implémentez l'écouteur en tant que Mock, vous pouvez ensuite 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.


4
2017-07-07 07:56



En Java 8, cela peut être un peu plus propre, en supposant que vous ayez 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 elle la compilation échouera avec quelques erreurs assez obscures car elle ne sera pas en mesure de trouver un remplacement approprié pour doAnswer.

Par exemple un ExecutorService qui exécute immédiatement tout Runnable transmis à execute() pourrait être mis en œuvre en utilisant:

doAnswer((i) -> {
  ((Runnable) i.getArguments()[0]).run();
  return null;
}).when(executor).execute(any());

4
2017-12-11 14:31



@ashley: travaille 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
2018-02-13 23:33