PowerMockito mockuje pojedynczą metodę statyczną i zwraca obiekt

98

Chcę wyszydzić statyczną metodę m1 z klasy, która zawiera 2 statyczne metody m1 i m2. Chcę, aby metoda m1 zwracała obiekt.

Wypróbowałem następujące

1)

PowerMockito.mockStatic(Static.class, new Answer<Long>() {
         @Override
         public Long answer(InvocationOnMock invocation) throws Throwable {
            return 1000l;
         }
      });

To wywołuje zarówno m1, jak i m2, które mają inny typ zwracania, więc zwraca błąd niezgodności typu zwracanego.

2) PowerMockito.when(Static.m1(param1, param2)).thenReturn(1000l); Ale to nie jest wywoływane, gdy wykonywany jest m1.

3) PowerMockito.mockPartial(Static.class, "m1"); Daje błąd kompilatora, który mockPartial jest niedostępny, który otrzymałem z http://code.google.com/p/powermock/wiki/MockitoUsage .

user1393653
źródło

Odpowiedzi:

136

To, co chcesz zrobić, to połączenie części 1 i wszystkich 2.

Musisz użyć PowerMockito.mockStatic, aby włączyć statyczne mockowanie dla wszystkich statycznych metod klasy. Oznacza to, że można je odgiąć przy użyciu składni when-thenReturn.

Ale 2-argumentowe przeciążenie mockStatic, którego używasz, dostarcza domyślnej strategii dla tego, co Mockito / PowerMock powinien zrobić, gdy wywołujesz metodę, której nie masz jawnie ukrytego w instancji pozorowanej.

Z javadoc :

Tworzy makietę klasy z określoną strategią odpowiedzi na interakcje. Jest to dość zaawansowana funkcja i zazwyczaj nie jest potrzebna do pisania porządnych testów. Jednak może być pomocny podczas pracy ze starszymi systemami. Jest to domyślna odpowiedź, więc będzie używana tylko wtedy, gdy nie zdeponujesz wywołania metody.

Domyślny domyślna strategia Stubbing jest tylko wartość null powrotnej 0 lub false dla obiektu, liczby oraz logiczne cenionych metod. Używając przeciążenia 2-argowego, mówisz "Nie, nie, nie, domyślnie użyj tej metody odpowiedzi podklasy Answer, aby uzyskać wartość domyślną. Zwraca ona wartość Long, więc jeśli masz metody statyczne, które zwracają coś niezgodnego z Długo, jest problem.

Zamiast tego użyj wersji mockStatic z jednym argumentem, aby włączyć kodowanie metod statycznych, a następnie użyj funkcji when-thenReturn, aby określić, co należy zrobić dla określonej metody. Na przykład:

import static org.mockito.Mockito.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

class ClassWithStatics {
  public static String getString() {
    return "String";
  }

  public static int getInt() {
    return 1;
  }
}

@RunWith(PowerMockRunner.class)
@PrepareForTest(ClassWithStatics.class)
public class StubJustOneStatic {
  @Test
  public void test() {
    PowerMockito.mockStatic(ClassWithStatics.class);

    when(ClassWithStatics.getString()).thenReturn("Hello!");

    System.out.println("String: " + ClassWithStatics.getString());
    System.out.println("Int: " + ClassWithStatics.getInt());
  }
}

Metoda statyczna o wartościach typu String jest skrócona, aby zwrócić „Hello!”, Podczas gdy metoda statyczna o wartościach int używa domyślnego kodu pośredniczącego, zwracając 0.

Tom Tresansky
źródło
1
Czy nie ma potrzeby odtwarzania?
Balaji Boggaram Ramanarayan
Hmm ... tak się wydaje. Może PowerMockito odtworzy dla Ciebie PowerMock? Ja też się nad tym zastanawiam.
djangofan
3
Ale co, jeśli muszę mieć pewność, że zostanie wywołana pewna metoda statyczna z precyzyjnymi argumentami?
elTomato
6
@PrepareForTestAdnotacja powinna być klasa, która wywołuje metodę statyczną, a nie klasy, gdzie jest metoda statyczna.
Hazel Troost
5
@HazelTroost - Nie, OP ma rację. Jest to klasa zawierająca metodę statyczną, którą należy przygotować do testu. Więc @PrepareForTest(ClassWithStatics.class)ma rację.
arry36