PowerMockito simule une méthode statique unique et renvoie un objet

98

Je veux moquer une méthode statique m1 d'une classe qui contient 2 méthodes statiques, m1 et m2. Et je veux que la méthode m1 renvoie un objet.

J'ai essayé ce qui suit

1)

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

Cela appelle à la fois m1 et m2, qui a un type de retour différent, ce qui donne une erreur d'incompatibilité de type de retour.

2) PowerMockito.when(Static.m1(param1, param2)).thenReturn(1000l); Mais ceci n'est pas appelé lorsque m1 est exécuté.

3) PowerMockito.mockPartial(Static.class, "m1"); Donne une erreur de compilateur qui mockPartial non disponible, que j'ai obtenue de http://code.google.com/p/powermock/wiki/MockitoUsage .

user1393653
la source

Réponses:

135

Ce que vous voulez faire est une combinaison d'une partie de 1 et de l'ensemble de 2.

Vous devez utiliser PowerMockito.mockStatic pour activer la simulation statique pour toutes les méthodes statiques d'une classe. Cela signifie qu'il est possible de les stuber en utilisant la syntaxe when-thenReturn.

Mais la surcharge à 2 arguments de mockStatic que vous utilisez fournit une stratégie par défaut pour ce que Mockito / PowerMock doit faire lorsque vous appelez une méthode que vous n'avez pas explicitement stubbée sur l'instance fictive.

Depuis le javadoc :

Crée une maquette de classe avec une stratégie spécifiée pour ses réponses aux interactions. C'est une fonctionnalité assez avancée et généralement vous n'en avez pas besoin pour écrire des tests décents. Cependant, cela peut être utile lorsque vous travaillez avec des systèmes hérités. C'est la réponse par défaut, elle ne sera donc utilisée que lorsque vous ne stoppez pas l'appel de méthode.

La stratégie de stubbing par défaut consiste à renvoyer simplement null, 0 ou false pour les méthodes objet, nombre et valeur booléenne. En utilisant la surcharge 2-arg, vous dites "Non, non, non, par défaut, utilisez la méthode de réponse de cette sous-classe Answer pour obtenir une valeur par défaut. Elle renvoie un Long, donc si vous avez des méthodes statiques qui renvoient quelque chose d'incompatible avec Longtemps, il y a un problème.

À la place, utilisez la version 1-arg de mockStatic pour activer le stubbing des méthodes statiques, puis utilisez when-thenReturn pour spécifier ce qu'il faut faire pour une méthode particulière. Par exemple:

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

La méthode statique à valeur de chaîne est stubbed pour retourner "Hello!", Tandis que la méthode statique à valeur int utilise le stubbing par défaut, renvoyant 0.

Tom Tresansky
la source
1
N'y a-t-il pas besoin de rejouer?
Balaji Boggaram Ramanarayan
Hmm ... un peu comme ça. Peut-être que PowerMockito fait la relecture de PowerMock pour vous? Je m'interroge également à ce sujet.
djangofan du
3
Mais que faire si je dois être sûr qu'une méthode statique est appelée avec des arguments précis?
elTomato
6
L' @PrepareForTestannotation doit être la classe qui appelle la méthode statique, pas la classe où se trouve la méthode statique.
Hazel Troost
5
@HazelTroost - Non, l'OP a raison. C'est la classe contenant la méthode statique qui doit être préparée pour le test. Alors, @PrepareForTest(ClassWithStatics.class)c'est vrai.
arry36