Eu montei uma classe com alguns testes e, em vez de usar @Before, gostaria de ter um método de instalação que seja executado apenas uma vez antes de todos os testes. Isso é possível com o Junit 4.8?
Eu montei uma classe com alguns testes e, em vez de usar @Before, gostaria de ter um método de instalação que seja executado apenas uma vez antes de todos os testes. Isso é possível com o Junit 4.8?
Respostas:
Embora eu concorde com @assylias que o uso @BeforeClassé uma solução clássica nem sempre é conveniente. O método anotado com @BeforeClassdeve ser estático. É muito inconveniente para alguns testes que precisam de instância de caso de teste. Por exemplo, testes baseados em primavera que costumam @Autowiredtrabalhar com serviços definidos no contexto da primavera.
Nesse caso, eu pessoalmente uso o setUp()método regular anotado com @Beforeanotação e gerencio meu sinalizador personalizado static(!) boolean:
private static boolean setUpIsDone = false;
.....
public void setUp() {
if (setUpIsDone) {
return;
}
// do the setup
setUpIsDone = true;
}
setUp()método está em uma superclasse - postou uma resposta abaixo, tentando resolver isso.
Você pode usar a BeforeClassanotação :
@BeforeClass
public static void setUpClass() {
//executed only once, before the first test
}
TheClassYouWant.classvez da sua chamada getClass ()? Esta é Java real: String.class.getName().
O JUnit 5 agora tem uma anotação @BeforeAll:
Indica que o método anotado deve ser executado antes de todos os métodos @Test na classe atual ou na hierarquia de classes; análogo ao @BeforeClass da JUnit 4. Tais métodos devem ser estáticos.
As anotações do ciclo de vida do JUnit 5 parecem ter finalmente acertado! Você pode adivinhar quais anotações estão disponíveis sem precisar procurar (por exemplo, @BeforeEach @AfterAll)
@BeforeClass, precisa ser static. A solução da IMO @ AlexR é melhor.
Quando setUp()está em uma superclasse da classe de teste (por exemplo, AbstractTestBaseabaixo), a resposta aceita pode ser modificada da seguinte maneira:
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();
}
}
Isso deve funcionar para um único setUp()método não estático , mas não consigo produzir um equivalente tearDown()sem entrar em um mundo de reflexão complexa ... Bounty aponta para quem pode!
Editar: Acabei de descobrir, durante a depuração, que a classe é instanciada antes de cada teste também. Acho que a anotação @BeforeClass é a melhor aqui.
Você também pode configurar o construtor, afinal a classe de teste é uma classe. Não tenho certeza se é uma prática ruim porque quase todos os outros métodos são anotados, mas funciona. Você pode criar um construtor assim:
public UT () {
// initialize once here
}
@Test
// Some test here...
O ctor será chamado antes dos testes porque eles não são estáticos.
Experimente esta solução: https://stackoverflow.com/a/46274919/907576 :
com @BeforeAllMethods/ @AfterAllMethodsanotação, você pode executar qualquer método na classe Test em um contexto de instância, onde todos os valores injetados estão disponíveis.
Minha solução suja é:
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;
}
}
...
}
Eu o uso como base para todos os meus testCases.
Se você não deseja forçar uma declaração de uma variável que é definida e verificada em cada subteste, a adição a um SuperTeste pode fazer:
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 ...
}
}
Eu resolvi esse problema assim:
Adicione à sua classe abstrata Base (quero dizer classe abstrata onde você inicializa seu driver no método setUpDriver () ) esta parte do código:
private static boolean started = false;
static{
if (!started) {
started = true;
try {
setUpDriver(); //method where you initialize your driver
} catch (MalformedURLException e) {
}
}
}
E agora, se suas classes de teste se estenderem da classe abstrata Base -, o método setUpDriver () será executado antes do primeiro @Test apenas uma vez por execução.
Use o método @PostConstruct do Spring para executar todo o trabalho de inicialização e esse método é executado antes que qualquer um dos @Test seja executado