Domanda

Sto utilizzando jmockit per i test unitari (con TestNG) e ho problemi a utilizzare la classe Expectations per deridere un metodo che accetta un tipo primitivo (booleano) come parametro, utilizzando un matcher.Ecco del codice di esempio che illustra il problema.

/******************************************************/
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 riga contenente la chiamata a invokeReturning(...) genera una NullPointerException.

Se cambio questa chiamata per non utilizzare un matcher, come in:

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

funziona proprio bene.Questo non va bene per me, perché nel mio codice reale sto effettivamente prendendo in giro un metodo multiparametro e devo usare un matcher su un altro argomento.In questo caso, la classe Expectations lo richiede Tutto gli argomenti utilizzano un matcher.

Sono abbastanza sicuro che si tratti di un bug, o forse non è possibile utilizzare i Matcher con tipi primitivi (mi renderebbe triste).Qualcuno ha riscontrato questo problema e sa come aggirarlo?

È stato utile?

Soluzione 2

Quindi il problema sembra essere in 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());
   }

La chiamata a typeVariable.getClass() non fa ciò che l'autore si aspetta e la chiamata al tipo Utilities.defaultValueFor restituisce null.Il de-autoboxing del valore booleano primitivo è da dove proviene l'NPE.

L'ho risolto modificando la chiamata invokeReturning(...) in:

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

Non sto più usando un matcher qui, ma è abbastanza buono per quello di cui ho bisogno.

Altri suggerimenti

il problema è la combinazione dell'utilizzo di Expectation e che Matchers non supporta il tipo primitivo.

Il codice Matchers si basa su Generic che sostanzialmente non supporta il tipo primitivo.In genere l'utilizzo dei Matcher è più per la corrispondenza del valore;con la funzionalità di auto-boxing/unboxing in Java 5, questo di solito non è un problema.

Ma Expectation di JMockit non lo usa per la corrispondenza del valore, lo usa per una sorta di analisi per determinare il tipo di firma della chiamata al metodo... che in questo caso i Matcher risulteranno in un tipo booleano mentre il tuo metodo è di tipo primitivo... quindi fallisce per deriderlo adeguatamente.

Mi dispiace di non poterti indicare alcuna soluzione alternativa a questo problema.Forse qualcun altro può aiutare.

Ho modificato JMockit (versione 0.982) in modo che "with(is(false))" e altre variazioni simili ora funzionino come previsto (non restituisce più null, ma il valore effettivo dell'argomento all'interno del matcher interno).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top