1. Panoramica
In questo rapido articolo, ci concentreremo su come eseguire i test JUnit utilizzando i test runner personalizzati.
In poche parole, per specificare il runner personalizzato, dovremo utilizzare l' annotazione @RunWith .
2. Preparazione
Cominciamo aggiungendo la dipendenza JUnit standard nel nostro pom.xml :
junit junit 4.12
3. Implementazione di un corridore personalizzato
Nell'esempio seguente, mostreremo come scrivere il nostro Runner personalizzato ed eseguirlo utilizzando @ RunWith .
Un JUnit Runner è una classe che estende la classe Runner astratta di JUnit ed è responsabile dell'esecuzione dei test JUnit , in genere utilizzando la riflessione.
Qui stiamo implementando metodi astratti della classe Runner :
public class TestRunner extends Runner { private Class testClass; public TestRunner(Class testClass) { super(); this.testClass = testClass; } @Override public Description getDescription() { return Description .createTestDescription(testClass, "My runner description"); } @Override public void run(RunNotifier notifier) { System.out.println("running the tests from MyRunner: " + testClass); try { Object testObject = testClass.newInstance(); for (Method method : testClass.getMethods()) { if (method.isAnnotationPresent(Test.class)) { notifier.fireTestStarted(Description .createTestDescription(testClass, method.getName())); method.invoke(testObject); notifier.fireTestFinished(Description .createTestDescription(testClass, method.getName())); } } } catch (Exception e) { throw new RuntimeException(e); } } }
Il metodo getDescription viene ereditato da Describable e restituisce una descrizione che contiene le informazioni che verranno successivamente esportate e che possono essere utilizzate da vari strumenti.
Nell'implementazione run , stiamo invocando i metodi di test di destinazione usando la reflection.
Abbiamo definito un costruttore che accetta un argomento Class ; questo è un requisito di JUnit. In fase di esecuzione, JUnit passerà la classe di test di destinazione a questo costruttore.
RunNotifier viene utilizzato per attivare eventi che contengono informazioni sull'avanzamento del test.
Usiamo il runner nella nostra classe di test:
public class Calculator { public int add(int a, int b) { return a + b; } } @RunWith(TestRunner.class) public class CalculatorTest { Calculator calculator = new Calculator(); @Test public void testAddition() { Syste.out.println("in testAddition"); assertEquals("addition", 8, calculator.add(5, 3)); } }
Il risultato che otteniamo:
------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.baeldung.junit.CalculatorTest running the tests from MyRunner: class com.baeldung.junit.CalculatorTest in testAddition Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.002 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
4. Corridori specializzati
Invece di estendere la classe Runner di basso livello , come abbiamo fatto nell'ultimo esempio, possiamo estendere una delle sottoclassi specializzate di Runner : ParentRunner o BlockJUnit4Runner .
La classe astratta ParentRunner esegue i test in modo gerarchico.
BlockJUnit4Runner è una classe concreta e se preferiamo personalizzare alcuni metodi, probabilmente estenderemo questa classe.
Vediamolo con un esempio:
public class BlockingTestRunner extends BlockJUnit4ClassRunner { public BlockingTestRunner(Class klass) throws InitializationError { super(klass); } @Override protected Statement methodInvoker(FrameworkMethod method, Object test) { System.out.println("invoking: " + method.getName()); return super.methodInvoker(method, test); } }
Annotare una classe con @RunWith (JUnit4.class) richiamerà sempre il runner JUnit 4 predefinito nella versione corrente di JUnit; questa classe alias l'attuale runner di classe JUnit 4 predefinito:
@RunWith(JUnit4.class) public class CalculatorTest { Calculator calculator = new Calculator(); @Test public void testAddition() { assertEquals("addition", 8, calculator.add(5, 3)); } }
5. conclusione
I JUnit Runner sono altamente adattabili e consentono allo sviluppatore di modificare la procedura di esecuzione del test e l'intero processo di test.
Se vogliamo solo apportare modifiche minori, è una buona idea dare un'occhiata ai metodi protetti di BlockJUnit4Class runner.
Alcune popolari implementazioni di terze parti di runner da utilizzare includono SpringJUnit4ClassRunner, MockitoJUnitRunner, HierarchicalContextRunner, Cucumber Runner e molto altro.
L'implementazione di tutti questi esempi e frammenti di codice può essere trovata nel progetto GitHub: questo è un progetto Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.