Question

J'utilise jmockit pour les tests unitaires (avec TestNG) et je ne parviens pas à utiliser la classe Expectations pour simuler une méthode qui prend un type primitif (booléen) en tant que paramètre, à l'aide d'un matcher. Voici un exemple de code illustrant le problème.

/******************************************************/
import static org.hamcrest.Matchers.is;

import mockit.Expectations;

import org.testng.annotations.Test;

public class PrimitiveMatcherTest {
  private MyClass obj;

  @Test
  public void testPrimitiveMatcher() {
    new Expectations(true) {
      MyClass c;
      {
        obj = c;
        invokeReturning(c.getFoo(with(is(false))), "bas");
      }
    };

    assert "bas".equals(obj.getFoo(false));

    Expectations.assertSatisfied();
  }

  public static class MyClass {
    public String getFoo(boolean arg) {
      if (arg) {
        return "foo";
      } else {
        return "bar";
      }
    }
  }
}
/******************************************************/

La ligne contenant l'appel à invokeReturning (...) lève une exception NullPointerException.

Si je modifie cet appel pour ne pas utiliser de matcher, comme dans:

invokeReturning(c.getFoo(false), "bas");

cela fonctionne très bien. Ce n'est pas bon pour moi, car dans mon vrai code, je me moque d'une méthode à plusieurs paramètres et je dois utiliser un matcher sur un autre argument. Dans ce cas, la classe Expectations requiert que tous les arguments utilisent un matcher.

Je suis presque sûr que c'est un bug, ou peut-être qu'il n'est pas possible d'utiliser des Matchers avec des types primitifs (cela me rendrait triste). Quelqu'un at-il rencontré ce problème et sait comment le résoudre?

Était-ce utile?

La solution 2

Le problème semble donc se trouver dans Expectations.with ():

   protected final <T> T with(Matcher<T> argumentMatcher)
   {
      argMatchers.add(argumentMatcher);

      TypeVariable<?> typeVariable = argumentMatcher.getClass().getTypeParameters()[0];

      return (T) Utilities.defaultValueForType(typeVariable.getClass());
   }

L'appel de typeVariable.getClass () ne fait pas ce que l'auteur attend et l'appel de type Utilities.defaultValueFor renvoie null. La suppression de la substitution automatique de la valeur booléenne primitive indique l'origine du NPE.

Je l'ai corrigé en modifiant l'appel invokeReturning (...) en:

invokeReturning(withEqual(false)), "bas");

Je n'utilise plus de matcher ici, mais c'est suffisant pour ce dont j'ai besoin.

Autres conseils

le problème est la combinaison de l'utilisation des attentes et du fait que Matchers ne prend pas en charge le type primitif.

Le code des correspondants s'appuie sur Generic, qui ne prend pas en charge le type primitif. Généralement, l'utilisation de Matchers est davantage utilisée pour la correspondance de valeur. avec le feater auto-boxing / unboxing de Java 5, ce n’est généralement pas un problème.

Mais Expectation de JMockit ne l'utilise pas pour faire correspondre la valeur, il l'utilise pour une sorte d'analyse syntaxique afin de déterminer le type de signature d'appel de la méthode. donc il ne parvient pas à se moquer correctement.

Je suis désolé de ne pouvoir vous dire aucune solution de contournement pour cela. Peut-être que quelqu'un d'autre peut aider.

J'ai modifié JMockit (version 0.982) pour que "avec (est (faux))" et d’autres variantes similaires fonctionnent maintenant comme prévu (il ne renvoie plus null, mais la valeur de l’argument réel dans l’interface interne).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top