Pregunta ¿Cómo evitar la herencia en los casos de prueba JUnit?


Tengo una serie de casos de prueba en JUnit. Todos ellos necesitan el mismo código para ejecutarse en su @BeforeClass método estático Es una duplicación de código y estoy tratando de deshacerme de ella. Una manera sucia de hacer esto es por herencia. ¿Hay algún otro mecanismo en JUnit que pueda ayudar?

PD. Escribí esta publicación en el blog sobre este mismo tema: http://www.yegor256.com/2015/05/25/unit-test-scaffolding.html


32
2017-07-16 04:14


origen


Respuestas:


La forma JUnit de componer código reutilizable (en lugar de heredarlo) son Reglas.

Ver https://github.com/junit-team/junit/wiki/Rules

Aquí hay una muestra tonta, pero obtendrá el punto.

import org.junit.rules.TestRule;
import org.junit.runners.model.Statement;
import org.junit.runner.Description;

public class MyTestRule implements TestRule {
  @Override
  public Statement apply(final Statement statement, Description description) {
    return new Statement() {
      public void evaluate() throws Throwable {
        // Here is BEFORE_CODE
        try {
          statement.evaluate();
        } finally {
          // Here is AFTER_CODE
        }
      }
    };
  }
}

A continuación, puede utilizar su TestRule de esta manera:

import org.junit.Rule;

public class MyTest {
    @Rule
    public MyTestRule myRule = new MyTestRule();
}

BEFORE_CODE y AFTER_CODE se ejecutarán alrededor de cada uno de tus métodos de prueba.

Si necesita ejecutar su código solo una vez por clase, use su TestRule como @ClassRule:

import org.junit.ClassRule;

public class MyTest {
    @ClassRule
    public static MyTestRule myRule = new MyTestRule();
}

Ahora, BEFORE_CODE y AFTER_CODE se ejecutará alrededor de cada una de tus clases de prueba.

@Regla el campo no es estático, @ClassRule el campo es

Una @ClassRule también se puede declarar en una Suite.

Tenga en cuenta que puede declarar varias reglas en una sola clase de prueba, así es como compone los ciclos de vida de prueba en suites de prueba, clases de prueba y niveles de métodos de prueba.

Una regla es un objeto que usted instancia en sus clases de prueba (estáticamente o no). Puede agregar parámetros contructor si es necesario.

HTH


31
2017-10-30 15:12



Si el método es algún tipo de utilidad, sepárelo a una clase diferente con un método estático y llame a ese método en su @BeforeClass.

Insisto en el hecho de que no use la herencia solo porque resuelve su problema, úsela cuando hacerlo crea sentido en la jerarquía de su clase.


4
2017-07-16 04:25



Puede crear un corredor de prueba

public class MyTestRunner extends BlockJUnit4ClassRunner {
  @Override
  protected Object createTest() throws Exception {
     Object test = super.createTest();
     doStuff();
  }

  public void doStuff(){
     //common code
  }
}


@RunWith(MyTestRunner.class)
public class MyTest1{
    @Test
    public void test1(){
      //test method
    }
}

2
2017-08-23 06:05



Los métodos estáticos no se heredan, por lo que la herencia no es una opción por defecto. Si te refieres a que estás moviendo el método a una clase principal común, entonces parece una opción pobre ya que solo obtienes un padre en Java. Una clase de soporte de prueba de algún tipo parece más apropiada. También es posible que esté viendo la necesidad de un prueba parametrizada.


1
2017-07-16 04:39



No hay absolutamente nada de malo en la herencia en este caso, en realidad es la única forma de evitar repetir este código en cada subclase. El hecho de que los métodos @BeforeClass tengan que declararse estáticos en JUnit es desafortunado, pero eso no debería detenerlo. Extienda la clase y el código de inicialización se ejecutará automáticamente sin tener que hacer nada.


1
2017-07-16 21:18



Si todas y cada clase necesita tener un @BeforeClass método anotado que es exactamente lo mismo que todos los demás, entonces la herencia no se siente ese mal para mí Si cada uno de estos métodos de inicialización simplemente comparte algunos código, podrías hacer un TestUtil clase con un comportamiento compartido y hacer llamadas a este comportamiento compartido de cada uno de los @BeforeClass métodos.


0
2017-07-16 04:26



Creo que si las clases tienen "es un"relación, la herencia es razonable.

Si la clase base es MyBeforeClass que define @BeforeClass método, y MyTestClass1 "es un" MyBeforeClass, MyTestClass1 extends MyBeforeClass está bien


0
2017-07-16 04:41