java - tutorial - mockito verify




Come fare finta di annullare metodi con mockito (7)

Come simulare i metodi con il tipo di reso vuoto?

Ho implementato un pattern Observer ma non riesco a deriderlo con Mockito perché non so come.

E ho cercato di trovare un esempio su Internet, ma non ci sono riuscito.

La mia classe sembra

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();
}

Il sistema non è attivato con simulazione. = (Voglio mostrare lo stato del sistema sopra menzionato e fare asserzione in base a loro.


@ashley: lavora per me

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);
} }

Aggiungendo a ciò che @sateesh ha detto, quando si vuole prendere in giro un metodo di annullamento per impedire al test di chiamarlo, è possibile utilizzare una Spy questo modo:

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

Quando si desidera eseguire il test, assicurarsi di chiamare il metodo in prova sull'oggetto spy e non sull'oggetto world . Per esempio:

assertEquals(0,spy.methodToTestThatShouldReturnZero());

Dai un'occhiata ai documenti dell'API Mockito. Come cita il documento collegato (Punto # 12) puoi usare una qualsiasi delle doThrow() , doAnswer() , doNothing() , doReturn() famiglia di metodi dal framework Mockito per simulare metodi void.

Per esempio,

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

o se vuoi combinarlo con il comportamento di follow-up,

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

Presumendo che si stia cercando di deridere il setter setState(String s) nella classe World qui sotto, il codice usa il metodo doAnswer per deridere il 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());

In Java 8 questo può essere reso un po 'più pulito, assumendo che si abbia un'importazione statica per org.mockito.Mockito.doAnswer :

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

Il return null; è importante e senza di esso la compilazione fallirà con alcuni errori piuttosto oscuri in quanto non sarà in grado di trovare un override adatto per doAnswer .

Ad esempio un ExecutorService che esegue immediatamente qualsiasi Runnable passato a execute() potrebbe essere implementato usando:

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

Penso che i tuoi problemi siano dovuti alla tua struttura di test. Ho trovato difficile mescolare il mocking con il metodo tradizionale di implementazione delle interfacce nella classe di test (come hai fatto qui).

Se implementi il ​​listener come Mock, puoi verificare l'interazione.

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

Questo dovrebbe soddisfare il fatto che il "Mondo" sta facendo la cosa giusta.


Penso di aver trovato una risposta più semplice a questa domanda, di chiamare il metodo reale per un solo metodo (anche se ha un ritorno vuoto) puoi farlo:

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

Oppure, puoi chiamare il metodo reale per tutti i metodi di quella classe, facendo così:

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

Come simulare metodi void con mockito - ci sono due opzioni:

  1. doAnswer - Se vogliamo che il nostro metodo del vuoto deriso faccia qualcosa ( doAnswer giro il comportamento nonostante sia vuoto).
  2. doThrow - Poi c'è Mockito.doThrow() se vuoi lanciare un'eccezione dal metodo del vuoto deriso.

Di seguito è riportato un esempio di come utilizzarlo (non un caso d'uso ideale ma solo per illustrare l'utilizzo di 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("[email protected]", "[email protected]");

    //some asserts
    assertThat(customer, is(notNullValue()));
    assertThat(customer.getEmail(), is(equalTo("[email protected]")));

}

@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("[email protected]", "[email protected]");

}
}

Puoi trovare maggiori dettagli su come simulare e testare metodi di annullamento con Mockito nel mio post Come deridere con Mockito (Una guida completa con esempi)







mockito