Jak zrobić mock to void metody z mockito

Jak mockować metody z void return type?

Zaimplementowałem wzór obserwatora, ale nie mogę wyśmiewać go z Mockito, bo nie wiem jak.

Próbowałem znaleźć przykład w Internecie, ale się nie udało.

Moja klasa wygląda jak

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

System nie jest uruchamiany za pomocą mocka. =( Chcę pokazać wyżej wymieniony stan systemu. I dokonać twierdzenia według nich.

Author: Janusz, 2010-02-16

10 answers

[[10]}spójrz na Mockito API docs . Jak wspomina dokument linkowany (Punkt # 12) można użyć dowolnego z doThrow(),doAnswer(),doNothing(),doReturn() rodzina metod od Mockito framework do mock void methods.

Na przykład,

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

Lub jeśli chcesz połączyć to z zachowaniem obserwacji,

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

Zakładając, że patrzysz na wyśmiewanie settera setState(String s) w świecie klas poniżej, kod używa metody doAnswer do wyśmiewania 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
Author: sateesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-25 03:41:18

Myślę, że znalazłem prostszą odpowiedź na to pytanie, aby wywołać prawdziwą metodę tylko dla jednej metody (nawet jeśli ma void return) możesz to zrobić:

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

Lub, można wywołać prawdziwą metodę dla wszystkich metod tej klasy, robiąc to:

<Object> <objectInstance> = mock(<Object>.class, Mockito.CALLS_REAL_METHODS);
 88
Author: MarcioB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-10 20:41:15

Dodając do tego, co powiedział @sateesh, gdy chcesz wyśmiewać metodę void, aby zapobiec wywołaniu testu, możesz użyć Spy w ten sposób:

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

Jeśli chcesz uruchomić test, upewnij się, że wywołujesz metodę w teście na obiekcie spy, a nie na obiekcie world. Na przykład:

assertEquals(0,spy.methodToTestThatShouldReturnZero());
 52
Author: Omri374,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-19 12:07:06

Rozwiązaniem tak zwanego problemu jest użycie spy Mockito.Szpieg(...) zamiast a mock Mockito.mock(..).

Szpieg pozwala nam na częściowe wyśmiewanie. Mockito jest w tym dobry. Ponieważ masz klasę, która nie jest kompletna, w ten sposób wyśmiewasz jakieś wymagane miejsce w tej klasie.
 50
Author: ibrahimyilmaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-19 15:47:25

Po Pierwsze: należy zawsze importować Mockito static, w ten sposób kod będzie znacznie bardziej czytelny (i intuicyjny):

import static org.mockito.Mockito.*;

Za częściowe wyśmiewanie i zachowanie oryginalnej funkcjonalności na reszcie Mockito oferuje "szpiega".

Możesz go użyć w następujący sposób:

private World world = spy(World.class);

Aby wyeliminować metodę z wykonania można użyć czegoś takiego:

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

Aby nadać pewne niestandardowe zachowanie metodzie, użyj "when" z "thenReturn":

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

Więcej przykłady proszę znaleźć próbki mockito w dokumencie.

 22
Author: fl0w,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-11 16:06:47

Jak wyśmiewać metody void za pomocą mockito - są dwie opcje:

  1. doAnswer - jeśli chcemy, aby nasza metoda wyśmiewana void zrobiła coś (wyśmiewała zachowanie pomimo bycia void).
  2. {[2] } - wtedy jest Mockito.doThrow() Jeśli chcesz wyrzucić wyjątek z metody mocked void.

Poniżej znajduje się przykład, jak go używać (nie jest to idealna podstawa, ale po prostu chciała zilustrować podstawowe użycie).

@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]");

}
}

Możesz znaleźć więcej szczegółów na temat tego, jak mock i test void metody z Mockito w moim poście Jak Mockito (obszerny poradnik z przykładami)

 18
Author: Dilini Rajapaksha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-29 02:52:16

Dodanie kolejnej odpowiedzi do grupy (nie zamierzona gra słów)...

Musisz wywołać metodę doAnswer, jeśli nie możesz\nie chcesz używać spy ' S. jednak niekoniecznie musisz toczyć własną ODPOWIEDŹ. Istnieje kilka domyślnych implementacji. W Szczególności, CallsRealMethods .

W praktyce wygląda to mniej więcej tak:

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

Lub:

doAnswer(Answers.CALLS_REAL_METHODS.get()).when(mock)
        .voidMethod(any(SomeParamClass.class));
 12
Author: javamonkey79,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-31 12:31:16

Myślę, że Twoje problemy są spowodowane strukturą testu. Trudno mi było mieszać szyderstwa z tradycyjną metodą implementacji interfejsów w klasie testowej(tak jak to zrobiłeś tutaj).

Jeśli zaimplementujesz słuchacza jako makietę, możesz zweryfikować interakcję.

Listener listener = mock(Listener.class);
w.addListener(listener);
world.doAction(..);
verify(listener).doAction();
To powinno cię zadowolić, że "świat" postępuje właściwie.
 5
Author: ashley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-07 07:56:30

W Javie 8 może to być nieco czystsze, zakładając, że masz statyczny import dla org.mockito.Mockito.doAnswer:

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

return null; jest ważne i bez niego kompilacja nie powiedzie się z dość niejasnymi błędami, ponieważ nie będzie w stanie znaleźć odpowiedniego nadpisania dla doAnswer.

Na przykład ExecutorService, który natychmiast wykonuje dowolne Runnable przekazane do execute(), może być zaimplementowane za pomocą:

doAnswer(i -> {
  ((Runnable) i.getArguments()[0]).run();
  return null;
}).when(executor).execute(any());
 5
Author: Tim B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 09:43:54

@ashley : działa dla mnie

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
Author: Yoga Gowda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-21 11:15:56