En test-klasse består gjerne av mange test-metoder og hver test-metode vil typisk først rigge opp en eller flere instanser og så teste at disse oppfører seg som forventet. Ta test-klassen for Counter
-klassen som eksempel:
Code Block |
---|
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class CounterTest { @Test public void testCounter() { Counter counter = new Counter(1, 3); assertEquals(1, counter.getCounter()); // sjekk om returverdi er 1 assertTrue(counter.count()); // sjekk om returverdi er true assertEquals(2, counter.getCounter()); // sjekk om returverdi er 2 assertFalse(counter.count()); // sjekk om returverdi er false assertEquals(3, counter.getCounter()); // sjekk om returverdi er 3 } @Test public void testGetCounter() { Counter counter = new Counter(1, 3); assertEquals(1, counter.getCounter()); counter.count(); assertEquals(2, counter.getCounter()); counter.count(); assertEquals(3, counter.getCounter()); } @Test public void testCount() { Counter counter = new Counter(1, 3); assertTrue(counter.count()); assertFalse(counter.count()); } } |
Her har vi tre test-metoder, som hver oppretter en instans og tester oppførselen til henholdsvis konstruktøren, getCounter
og count()
. Vi ser at alle rigger opp like instanser og dersom dette hadde vært mer enn én linje kode, så hadde det vært greit å samle denne koden i en egen hjelpemetode, f.eks. kalt setUp, som kalles i begynnelsen av hver test-metode:
Code Block |
---|
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; public class CounterTest { private Counter counter; private void setUp() { counter = new Counter(1, 3); } @Test public void testCounter() { setUp(); assertEquals(1, counter.getCounter()); // sjekk om returverdi er 1 assertTrue(counter.count()); // sjekk om returverdi er true assertEquals(2, counter.getCounter()); // sjekk om returverdi er 2 assertFalse(counter.count()); // sjekk om returverdi er false assertEquals(3, counter.getCounter()); // sjekk om returverdi er 3 } @Test public void testGetCounter() { setUp(); assertEquals(1, counter.getCounter()); counter.count(); assertEquals(2, counter.getCounter()); counter.count(); assertEquals(3, counter.getCounter()); } @Test public void testCount() { setUp(); assertTrue(counter.count()); assertFalse(counter.count()); } } |
Siden dette er et relativt vanlig tilfelle har JUnit-rammeverket innebygget støtte for en slik hjelpemetode. Ved å sette metoden til public og legget til @BeforeEach over testen vil den kjøres automatisk før hver test.
Code Block |
---|
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class CounterTest { private Counter counter; @BeforeEach public void setUp() { counter = new Counter(1, 3); } @Test public void testCounter() { assertEquals(1, counter.getCounter()); // sjekk om returverdi er 1 assertTrue(counter.count()); // sjekk om returverdi er true assertEquals(2, counter.getCounter()); // sjekk om returverdi er 2 assertFalse(counter.count()); // sjekk om returverdi er false assertEquals(3, counter.getCounter()); // sjekk om returverdi er 3 } @Test public void testGetCounter() { assertEquals(1, counter.getCounter()); counter.count(); assertEquals(2, counter.getCounter()); counter.count(); assertEquals(3, counter.getCounter()); } @Test public void testCount() { assertTrue(counter.count()); assertFalse(counter.count()); } } |
I noen tilfeller vil det som rigges opp av setUp()
-metoden også måtte rigges ned, for ikke å forsøple systemet testene kjøres på. Det kan f.eks. være praktisk å opprette noen temporære datafiler i setUp()
-metoden, og da må de jo fjernes etterpå. Det vil ikke være særlig ryddig å gjøre dette i test-metodene selv, siden en da må bruke try/finally
for å sikre at det skjer uansett utfall av testen. Derfor støtter JUnit-rammeverket en tearDown()
-metode, som kalles automatisk etter at hver test-metode er kjørt, uansett om testen ble avbrutt eller ikke. Som for setUp()
er det bare å legge til @AfterEach over metoden. I tilfellet over er ikke en slik metode nødvendig (hver test-metode kjøres på en ny instans av CounterTest), men en test-klasse med tearDown()
-metode kunne sett slik ut:
Code Block |
---|
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class CounterTest { private Counter counter; @BeforeEach public void setUp() { counter = new Counter(1, 3); } @AfterEach public void tearDown() { counter = null; } @Test public void testCounter() { assertEquals(1, counter.getCounter()); // sjekk om returverdi er 1 assertTrue(counter.count()); // sjekk om returverdi er true assertEquals(2, counter.getCounter()); // sjekk om returverdi er 2 assertFalse(counter.count()); // sjekk om returverdi er false assertEquals(3, counter.getCounter()); // sjekk om returverdi er 3 } @Test public void testGetCounter() { Counter counter = new Counter(1, 3); assertEquals(1, counter.getCounter()); counter.count(); assertEquals(2, counter.getCounter()); counter.count(); assertEquals(3, counter.getCounter()); } @Test public void testCount() { Counter counter = new Counter(1, 3); assertTrue(counter.count()); assertFalse(counter.count()); } } |
I praksis brukes ikke tearDown()
så ofte, men når setUp endrer tilstanden til systemet utenfor testene, så bør en vurdere å bruke den!
Sider om Enhetstesting med JUnit: