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 eso posible con Junit 4.8?
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 eso posible con Junit 4.8?
Respuestas:
Aunque estoy de acuerdo con @assylias en que usar @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 una instancia de caso de prueba. Por ejemplo, pruebas basadas en Spring que usan@Autowired
funcionar con servicios definidos en el contexto de Spring.
En este caso, personalmente uso el setUp()
método regular anotado con @Before
anotación y administro mi bandera personalizada static
(!) boolean
:
private static boolean setUpIsDone = false;
.....
@Before
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()
método esté en una superclase: he publicado una respuesta a continuación para intentar resolver esto.
Puede utilizar la BeforeClass
anotación :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.class
lugar de su llamada getClass ()? Esto es real de Java: String.class.getName()
.
JUnit 5 ahora tiene una anotación @BeforeAll:
Indica que el método anotado debe ejecutarse antes que todos los métodos @Test en la clase actual o jerarquía de clases; análogo a @BeforeClass de JUnit 4. Tales métodos deben ser estáticos.
¡Las anotaciones del ciclo de vida de JUnit 5 parecen haberlo hecho bien finalmente! Puede adivinar qué anotaciones están disponibles sin siquiera mirar (por ejemplo, @BeforeEach @AfterAll)
@BeforeClass
, tiene que serlo static
. La solución de IMO @ AlexR es mejor.
Cuando setUp()
está en una superclase de la clase de prueba (por ejemplo, a AbstractTestBase
continuación), la respuesta aceptada se puede modificar 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 un solo setUp()
método no estático , pero no puedo producir un equivalente tearDown()
sin perderme en un mundo de reflexión compleja ... ¡Puntos de recompensa para cualquiera que pueda!
Editar: descubrí mientras depuraba que la clase también se instancia antes de cada prueba. Supongo que la anotación @BeforeClass es la mejor aquí.
También puede configurar 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. Podrías crear un constructor como ese:
public UT () {
// initialize once here
}
@Test
// Some test here...
El ctor se llamará antes de las pruebas porque no son estáticas.
Pruebe esta solución: https://stackoverflow.com/a/46274919/907576 :
con @BeforeAllMethods
/ @AfterAllMethods
annotation puede ejecutar cualquier método en la clase Test en un contexto de instancia, donde todos los valores inyectados están disponibles.
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 base para todos mis testCases.
Si no desea forzar la declaración de una variable que se establece y se verifica en cada subprueba, agregar esto a una SuperTest podría hacer:
public abstract class SuperTest {
private static final ConcurrentHashMap<Class, Boolean> INITIALIZED = new ConcurrentHashMap<>();
protected final boolean initialized() {
final boolean[] absent = {false};
INITIALIZED.computeIfAbsent(this.getClass(), (klass)-> {
return absent[0] = true;
});
return !absent[0];
}
}
public class SubTest extends SuperTest {
@Before
public void before() {
if ( super.initialized() ) return;
... magic ...
}
}
Resolví este problema así:
Agregue a su clase abstracta base (me refiero a la clase abstracta donde inicializa su controlador en el método setUpDriver () ) esta parte del código:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
Y ahora, si sus clases de prueba se extienden desde la clase abstracta Base -> el método setUpDriver () se ejecutará antes del primer @Test solo UNA vez por ejecución.
Use el método @PostConstruct de Spring para hacer todo el trabajo de inicialización y este método se ejecuta antes de que se ejecute cualquiera de las @Test