Pregunta

Estoy usando jmockit para pruebas unitarias (con TestNG) y tengo problemas para usar la clase Expectations para simular un método que toma un tipo primitivo (booleano) como parámetro, usando un comparador.Aquí hay un código de muestra que ilustra el 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 línea que contiene la llamada a invokeReturning(...) genera una NullPointerException.

Si cambio esta llamada para no usar un comparador, como en:

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

funciona bien.Esto no es bueno para mí, porque en mi código real en realidad me estoy burlando de un método multiparamétrico y necesito usar un comparador en otro argumento.En este caso, la clase Expectativas requiere que todo Los argumentos utilizan un comparador.

Estoy bastante seguro de que esto es un error, o tal vez no sea posible usar Matchers con tipos primitivos (eso me entristecería).¿Alguien ha encontrado este problema y sabe cómo solucionarlo?

¿Fue útil?

Solución 2

Entonces el problema parece estar en 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 llamada a typeVariable.getClass() no hace lo que el autor espera y la llamada al tipo Utilities.defaultValueFor devuelve nulo.La eliminación automática del valor booleano primitivo es de donde proviene el NPE.

Lo arreglé cambiando la llamada invokeReturning(...) a:

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

Ya no uso un comparador aquí, pero es lo suficientemente bueno para lo que necesito.

Otros consejos

el problema es la combinación del uso de expectativas y que Matchers no admite tipos primitivos.

El código de Matchers se basa en Generic, que básicamente no admite tipos primitivos.Normalmente, el uso de Matchers es más para igualar el valor;Con la característica de auto-boxing/unboxing en Java 5, esto no suele ser un problema.

Pero la expectativa de JMockit no lo usa para hacer coincidir valores, lo usa para algún tipo de análisis para determinar el tipo de firma de llamada al método... que en este caso los Matchers darán como resultado un tipo booleano mientras que su método es de tipo primitivo... por lo que falla para burlarse de ello adecuadamente.

Lamento no poder ofrecerle ninguna solución para esto.Quizás alguien más pueda ayudar.

Cambié JMockit (versión 0.982) para que "with(is(false))" y otras variaciones similares ahora funcionen como se esperaba (ya no devuelve nulo, sino el valor del argumento real dentro del comparador interno).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top