Pregunta

En una clase de prueba, me gustaría ofrecer mi propia sobrecarga de assertEquals con un poco de lógica especial no depender de Object.equals. Por desgracia, eso no funciona porque tan pronto como Declaro mi método assertEquals localmente, Java no encuentra la importación estática de org.junit.Assert.* más.

¿Hay una manera de evitar esto? Es decir. ¿hay una manera de proporcionar una sobrecarga adicional para un método estáticamente importada? (La solución más obvia es para nombrar el método diferente, pero esta solución no tiene el mismo atractivo estético.)

Mi archivo de clase de prueba es como la siguiente:

package org.foo.bar;

import static org.junit.Assert.*;

import org.junit.Test;

public class BarTest {
    private static void assertEquals(Bar expected, Bar other) {
        // Some custom logic to test equality.
    }

    @Test
    public void testGetFoo() throws Exception {
        Bar a = new Bar();
        assertEquals(42, a.getFoo()); // Error *
    }

    @Test
    public void testCopyConstructor() throws Exception {
        Bar a = new Bar();
        // Fill a.
        Bar b = new Bar(a);
        assertEquals(a, b);
    }
}

Error * es “El assertEquals(Bar, Bar) método en el BarTest tipo no es aplicable para la (int, int) argumentos.”

¿Fue útil?

Solución

Hay dos secciones en esta respuesta - uno sobre el error de compilación, y el otro sobre el uso de assertEquals ()

El problema es que hay dos assertEquals () en dos espacios de nombres diferentes -. Uno presente en el espacio de nombres org.junit.Assert, el otro en el espacio de nombres org.foo.bar.BarTest (el espacio de nombres actual)

El error es reportado por el compilador debido a la reglas de remedo declaran en la especificación del lenguaje Java . La importación estática de Assert.assertEquals () está ensombrecido por las assertEquals () declarados en la clase BarTest.

La solución (siempre en el caso de las declaraciones de sombra) es utilizar FQNs (Los nombres completos). Si se va a utilizar assertEquals (...) de la clase JUnit Assert, utilice

org.junit.Assert.assertEquals(...)

y cuando se necesita usar su declaración sólo tiene que utilizar

assertEquals(...)

en BarTest única, en la que es la sombra. En todas las demás clases que requieren sólo una de Assert.assertEquals () o BarTest.asserEquals (), puede importar afirmar o BarTest (no creo que tendría que importar BarTest en otro lugar, pero declaró no obstante).

Cuando no hay sombra, puede permitirse el lujo de simplemente importar la clase o método estático y utilizarlo sin FQNs.

material adicional para pensar

Assert.assertEquals () utiliza internamente el método de las clases de los argumentos de equals (). La declaración de un assertEquals () en su caso de prueba, viola el principio DRY, ya que los iguales () de tipo debe ser implementado y usado consistentemente - poner dos implementaciones diferentes en el código fuente y en las pruebas de unidad está obligado a causar confusión <. / p>

El mejor enfoque sería implementar equals () en la barra, y luego usar Assert.assertEquals () en los casos de prueba. Si ya tiene, la que no necesita una BarTest.assertEquals (). El pseudocódigo para assertEquals () es algo así como la siguiente

  1. Si ambos argumentos son nulos, de vuelta verdad.
  2. Si espera no es nulo, a continuación, invoque iguales () en esperada pasar el real como argumento. Devuelve verdadero si el objeto son iguales.
  3. Si los objetos no son iguales, lanzar una AssertionError con un mensaje formateado.

Otros consejos

Una posible solución para su ejemplo específico de llamar assertEquals(Bar, Bar) en una prueba unitaria sería extender la clase con uno que proporciona el método estático, como sigue:

class BarAssert extends Assert {
  public static void assertEquals(Bar expected, Bar other) {
        // Some custom logic to test equality.
    }
}

A continuación, podría incluir import static BarAssert.assertEquals; y usar su lógica personalizada.

Las disculpas que esto no responde directamente a la pregunta, y está más dirigido a su ejemplo. De acuerdo con mi comentario adjunto a la pregunta, yo recomendaría contra de este enfoque.

La única manera de hacerlo es calificar totalmente uno o el otro.

import static org.junit.Assert.*;

import org.junit.Test;

public class BarTest {

    private static void assertEquals(Bar expected, Bar other) {
        // Some custom logic to test equality.
    }

    @Test
    public void testGetFoo() throws Exception {
        Bar a = new Bar();
        org.junit.Assert.assertEquals(42, a.getFoo());
    }
}
this.assertEquals(a,b);

o

BarTest.assertEquals(a,b);

Me quedo con el primero, ya que a pesar de ser un método estático, usted tiene que tener una instancia de utilizarla (que es privado) y this no estará sujeto a los caprichos de los futuros cambios de nombre.

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