tutorial examples espaƱol descargar java junit

java - examples - assert es igual a int flotante largo



junit tutorial (5)

¿Hay una forma elegante de afirmar números iguales ignorando sus clases? Quiero usarlo en el marco de pruebas JUnit, pero por ejemplo

Assert.assertEquals(1,1L)

falla con java.lang.AssertionError: expected: java.lang.Integer <1> pero fue: java.lang.Long <1>

Espero que haya un buen método en alguna parte que compare solo el valor y funcione con int, long, float, byte, double, BigDecimal, BigInteger, lo que sea ...


Cree sus propios métodos afirmar y compare los valores dobles para los primitivos. Si se usa un BigDecimal , el valor primitivo se debe convertir a un BigDecimal

static void assertEquals(Number number1, Number number2) { Assert.assertEquals(number1.doubleValue(), number2.doubleValue()); } static void assertEquals(BigDecimal number1, BigDecimal number2) { if (number2.compareTo(number1) != 0) { Assert.fail("Values are not equal. ..... "); } } static void assertEquals(Number number1, BigDecimal number2) { assertEquals(new BigDecimal(number1.doubleValue()), number2); } static void assertEquals(BigDecimal number1, Number number2) { assertEquals(number2, number1); }

Se puede usar de esta manera:

assertEquals(1, new BigDecimal("1.0")); assertEquals(1.0d, 1); assertEquals(new Float(1.0f), 1.0d); assertEquals(new BigDecimal("1.00000"), new BigDecimal("1.0")); ...


Creo que para aceptar los ocho tipos de valores numéricos (primitivo y objeto), el método tiene que tomar argumentos de cadena. La persona que llama tendrá que recordar lanzar el valor a la cadena por este modismo:

""+value

Además, en caso de que el valor no sea un entero ( int , Integer , long , Long ) sino una representación de coma flotante ( float , double , Float , Double ), el método también debe tomar un argumento epsilon para tolerar la imprecisión debido a la representación.

Así que aquí hay una idea de implementación (por ahora ignoro los casos de NaN y ceros positivos y negativos de doble; estos pueden agregarse si se necesita una implementación verdaderamente sólida)

private static boolean equalsNumerically(String n1String , String n2String , double epsilon) { try { Long n1Long = new Long(n1String); Long n2Long = new Long(n2String); return n1Long.equals(n2Long); } catch (NumberFormatException e) { /* * If either one of the number is not an integer, try comparing * the two as Double */ try { Double n1Double = new Double(n1String); Double n2Double = new Double(n2String); double delta = ( n1Double - n2Double) / n2Double; if (delta<epsilon) { return true; } else { return false; } } catch (NumberFormatException e2) { return false; } } }

Código de prueba

int primitiveInt = 1; long primitiveLong = 1L; float primitiveFloat = 0.999999F; double primitiveDouble = 0.999999D; Integer objectInt = new Integer(1); Long objectLong = new Long(1); Float objectFloat = new Float(0.999999); Double objectDouble = new Double(0.999999); final double epsilon = 1E-3; Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, 0)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+primitiveLong, 0): %s %s %s%n" , primitiveInt, primitiveLong, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, epsilon)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+primitiveLong, epsilon)): %s %s %s%n" , primitiveInt, primitiveLong, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveFloat, epsilon)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+primitiveFloat, 0): %s %s %s%n" , primitiveInt, primitiveFloat, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveDouble, epsilon)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+primitiveDouble, epsilon): %s %s %s%n" , primitiveInt, primitiveDouble, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectInt, 0)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+objectInt, 0): %s %s %s%n" , primitiveInt, objectInt, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectLong, 0)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+objectLong" + ", /"/"+objectLong, 0): %s %s %s%n" , primitiveInt, primitiveLong, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectFloat, epsilon)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+objectFloat, epsilon)): %s %s %s%n" , primitiveInt, objectFloat, epsilon); Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectDouble, epsilon)); System.out.format("Test passed: " + "Assert.assertTrue(equalsNumerically(/"/"+primitiveInt" + ", /"/"+objectDouble, 0): %s %s %s%n" , primitiveInt, objectDouble, epsilon);

Salida de prueba

Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, 0): 1 1 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveLong, epsilon)): 1 1 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveFloat, 0): 1 0.999999 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+primitiveDouble, epsilon): 1 0.999999 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectInt, 0): 1 1 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectLong, 0): 1 1 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectFloat, epsilon)): 1 0.999999 0.001 Test passed: Assert.assertTrue(equalsNumerically(""+primitiveInt, ""+objectDouble, 0): 1 0.999999 0.001


De acuerdo con mi lectura del JLS, la resolución de sobrecarga para

Assert.assertEquals(1,1L)

debería resolver a

Assert.assertEquals(long, long)

(Para el registro, assertEquals(long, long) , assertEquals(float, float) y assertEquals(double, double) son aplicables por invocación estricta , y el primero es el más específico; ver JLS 15.12.2.2 . El contexto de invocación estricta permite el ensanche primitivo, pero no el de boxeo o unboxing.)

Si (como lo sugiere la evidencia) su llamada se está resolviendo en Assert.assertEquals(Object, Object) , eso implica que uno de los operandos ya debe ser un tipo encajonado. El problema con esa sobrecarga es que está usando el método equals(Object) para comparar objetos, y el contrato para ese método especifica que el resultado es false si los tipos respectivos de los objetos son diferentes.

Si eso es lo que está sucediendo en su código real, entonces dudo que la sugerencia de usar el is(T) Matcher funcione tampoco. El matizador is(T) es equivalente a is(equalTo(T)) y el último se basa en equals(Object) ...

¿Existe un "buen método" existente?

AFAIK, no.

Creo que la verdadera solución es estar un poco más atento a los tipos; p.ej

int i = 1; Long l = 1L; Assert.assertEquals(i, l); // Fails Assert.assertEquals((long) i, l); // OK - assertEquals(Object, Object) Assert.assertEquals((Long) i, l); // OK - assertEquals(Object, Object) Assert.assertEquals(i, (int) l); // OK - assertEquals(int, int) Assert.assertEquals(i, (long) l); // OK - assertEquals(long, long)

Escribir un Matcher personalizado también funcionaría.


Envuelva esa funcionalidad en su propio Matcher y assertThat con assertThat .

Matriz de muestra:

class IsAnyNumber extends BaseMatcher { final Object expected; //... public boolean matches(Object actual) { // compare / transform / check type / ensure: String, double, int, long // example via BigDecimal as seen from Mena (without checks) return new BigDecimal(expected).equals(new BigDecimal(actual)); } // ... } // somewhere else: public static IsAnyNumber is(Object expected) { return new IsAnyNumber(expected); }

En sus pruebas, llama a ese método estático:

assertThat(1, is(1L)); assertThat(1, is(1.0)); assertThat(1L, is(1));

De esta forma, puede reutilizar su marcador y la declaración de afirmación es más legible al final.

Descargo de responsabilidad: este es solo un pseudocódigo y todavía no se probó, pero debería funcionar con algunos ajustes.

Pero ten cuidado también de Comparar números en Java


Una solución con algunos gastos generales sería envolver los valores en objetos BigDecimal , ya que las sobrecargas del constructor BigDecimal toman primitivas long , int y primitivas double .

Como el new BigDecimal(1l).equals(new BigDecimal(1.0)) es true ,

Assert.assertEquals(new BigDecimal(1.0), new BigDecimal(1l));

debería funcionar para usted.

Editar

Como afirma Hulk a continuación, la escala de los objetos BigDecimal se usa en la comparación de equals , pero no en la comparación compareTo . Si bien la escala se establece en un valor predeterminado 0 para el constructor que toma long , se deduce a través de un cálculo en el constructor que toma el double . Por lo tanto, la forma más segura de comparar valores (es decir, en casos extremos para valores double ) podría ser invocar compareTo y comprobar que el resultado es 0 lugar.