2012-08-23 32 views
74

Configuré una clase con un par de pruebas y en lugar de usar @Before Me gustaría tener un método de configuración que se ejecute solo una vez antes de todas las pruebas. ¿Es posible con Junit 4.8?Junit: ejecutar el método de configuración una vez

+0

Eche un vistazo a RunListener: http://stackoverflow.com/a/14773170/548473 – GKislin

Respuesta

130

Aunque estoy de acuerdo con que el uso de @assylias @BeforeClass es una solución clásica no siempre es conveniente. El método anotado con @BeforeClass debe ser estático. Es muy inconveniente para algunas pruebas que necesitan instancia de caso de prueba. Por ejemplo, las pruebas basadas en Spring que usan @Autowired para trabajar con servicios definidos en el contexto de primavera.

En este caso, yo personalmente uso regular setUp() método anotado con @Before anotación y gestionar mi costumbre boolean bandera:

private static boolean setUpIsDone = false; 
..... 
public void setUp() { 
    if (setUpIsDone) { 
     return; 
    } 
    // do the setup 
    setUpIsDone = true; 
} 
+15

La variable setUpIsDone debe ser estática, junto con los otros objetos que desee utilizar en cada método @Test que se instancia en setUp(). –

+4

Añadiendo al comentario de Kenny Cason por qué debe ser estático. Debe ser estático porque JUnit instancia una nueva instancia de la clase de prueba para cada método @Test. La variable de instancia se restablecerá a su valor predeterminado (falso) para cada instancia si no es estática. Consulte para obtener más información: http://martinfowler.com/bliki/JunitNewInstance.html –

+2

Esto funciona, excepto en el caso en que el método 'setUp()' está en una superclase - ha publicado una [respuesta] (http: // stackoverflow .com/questions/12087959 # 31117171) abajo tratando de resolver esto. –

67

Puede utilizar the BeforeClass annotation:

@BeforeClass 
public static void setUpClass() { 
    //executed only once, before the first test 
} 
+6

No puedo usar esto, tengo unos pocos métodos de instalación que se basan en componentes no estáticos como getClass() – Bober02

+1

@ Bober02 BeforeClass necesita ser estático de hecho. Si no puede usar eso, la otra respuesta proporciona una solución alternativa. – assylias

+2

¿Seguro que no puede usar 'TheClassYouWant.class' en lugar de llamar a getClass()? Esto es Java real: 'String.class.getName()'. – stolsvik

4

Cuando setUp() está en una superclase de la prueba real, la respuesta aceptada puede ser modificado de la siguiente manera :

public abstract class AbstractTestBase { 
    private static Class<? extends AbstractTestBase> testClass; 
    ..... 
    public void setUp() { 
     if (this.getClass().equals(testClass)) { 
      return; 
     } 

     // do the setup - once per concrete test class 
     ..... 
     testClass = this.getClass(); 
    } 
} 

Esto debería funcionar para una sola configuración no estática método() pero soy incapaz de producir un equivalente para tearDown() sin perderse en un mundo de reflexión compleja ... puntos de bonificación para cualquiera que pueda!

0

Editar: acabo de descubrir durante la depuración que la clase se crea una instancia antes de cada prueba también. Supongo que la anotación @BeforeClass es la mejor aquí.

Puede configurar también en el constructor, la clase de prueba es una clase después de todo. No estoy seguro de si es una mala práctica porque casi todos los demás métodos están anotados, pero funciona. Se puede crear un constructor de esa manera:

public UT() { 
    // initialize once here 
} 
@Test 
// Some test here... 

La Héctor se llamará antes de las pruebas, ya que no son estáticas.

16

JUnit 5 tiene ahora una anotación @BeforeAll:

denota que el método anotado debe ser ejecutado antes de que todo @test métodos de la clase actual o jerarquía de clases; análoga a JUnit 4's @BeforeClass. Dichos métodos deben ser estáticos.

¡Las anotaciones del ciclo de vida de JUnit 5 parecen haber llegado finalmente a su fin! Puede adivinar qué anotaciones disponible sin mirar siquiera (por ejemplo @BeforeEach @AfterAll)

+1

Tiene el mismo problema que '@ BeforeClass', necesita ser' static'. La solución de IMO @ AlexR es más agradable. – zengr

+0

@zengr tienden a estar de acuerdo con usted: como le dije a AlexR, su solución requiere que todas las clases de prueba subclasen de una clase CommonTest si solo se ejecuta una vez. Pero es tan simple como puede ser, y en mi humilde opinión, probablemente no deba utilizar una solución "fantasiosa" suministrada por el marco cuando el lenguaje ofrece un mecanismo simple. A menos que haya una buena razón, por supuesto. Además, usando una cosa simple como la suya, con un buen nombre de tipo "hace lo que dice en lata", ayuda con la legibilidad. –

+0

Habiendo dicho esto, de nuevo en mi humilde opinión, parece haber mucha más justificación para tener una anotación de "Después de todo": sería muy difícil idear un mecanismo para detectar cuándo se realizaron todas las pruebas. Por el contrario, por supuesto, los puristas probablemente dirán que nunca debería tener que hacer una "limpieza final", es decir, que cada "lágrima" debería dejar todos los recursos en un estado prístino ... ¡y probablemente tengan razón! –

0

Pruebe esta solución: https://stackoverflow.com/a/46274919/907576:

con @BeforeAllMethods/@AfterAllMethods anotación que podría ejecutar cualquier método en la clase de prueba en un contexto ejemplo, donde todos los valores inyectados están disponibles.

0

Mi solución sucia es:

public class TestCaseExtended extends TestCase { 

    private boolean isInitialized = false; 
    private int serId; 

    @Override 
    public void setUp() throws Exception { 
     super.setUp(); 
     if(!isInitialized) { 
      loadSaveNewSerId(); 
      emptyTestResultsDirectory(); 
      isInitialized = true; 
     } 
    } 

    ... 

} 

lo uso como una base de base a todos mis casos de prueba.

+0

public class TestCaseExtended extends TestCase { private static boolean isInitialized = false; private static TestCaseExtended caseExtended; private int serId; @Override public void setUp() throws Excepción { super.setUp(); if (! IsInitialized) { caseExtended = new TestCaseExtended(); caseExtended.loadSaveNewSerId(); caseExtended.emptyTestResultsDirectory(); isInitialized = true; } } –

Cuestiones relacionadas