Loading the lesson...
In the print dialog, choose "Save as PDF" as the destination.
Frameworks, annotations, lifecycle, and practical JUnit 5 examples
function, method, procedure, module, or object| Tool | What it offers |
|---|---|
JUnit | Free Java testing tool, provides assertions to identify test methods |
NUnit | Widely used for .NET languages, open source, supports parallel data-driven tests |
JMockit | Open source, offers mocking plus Line/Path/Data coverage metrics |
EMMA | Open-source Java coverage toolkit (method, line, basic block), no external dependencies |
PHPUnit | Unit testing tool for PHP, tests small code portions separately with predefined assertions |
JUnit 5 is the most widely used Java testing framework, built to embrace Java 8+ style coding (lambda expressions); requires Java 8 or higherJUnit 3 and JUnit 4 testsJUnit 5
Platform
TestEngine API, Console Launcher, build plugins
Jupiter
New programming/extension model, own TestEngine
Vintage
Runs old JUnit 3/JUnit 4 tests on JUnit 5
| Annotation | What it does |
|---|---|
@Test | Marks a method as a test |
@BeforeEach / @AfterEach | Run before/after every test method |
@BeforeAll / @AfterAll | Run once for the whole class (must be static) |
@DisplayName | Custom, readable name for a class or test method |
@Disabled | Skip a test class or method |
@RepeatedTest / @ParameterizedTest | Repeat a test, or drive it with multiple input sets |
@Nested | Group related tests inside inner classes |
@Tag | Filter/discover tests by tag |
@BeforeAll
once, before any test
@BeforeEach
@Test
@AfterEach
@AfterAll
once, after all tests
@BeforeEach runs, then the @Test method, then @AfterEachpublic class Calculator {
public int add(int a, int b) { return a + b; }
public double divide(int a, int b) {
if (b == 0) throw new IllegalArgumentException("Cannot divide by zero");
return (double) a / b;
}
}
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void init() { calculator = new Calculator(); }
@Test
@DisplayName("Test Addition: 5 + 3 = 8")
void testAddition() {
assertEquals(8, calculator.add(5, 3), "5 + 3 should equal 8");
}
@Test
void testDivisionByZero() {
assertThrows(IllegalArgumentException.class,
() -> calculator.divide(10, 0));
}
}Calculator class and its first JUnit 5 test class.assertEquals(10, 5 * 2, "5 * 2 should equal 10");
assertEquals(3.14, 3.141, 0.01); // delta comparison
assertTrue(5 > 3);
assertNull(nullString);
assertArrayEquals(expected, actual);
assertSame(a, c); // same object reference
assertThrows(IllegalArgumentException.class, () -> calculator.divide(10, 0));
assertTimeout(Duration.ofMillis(100), () -> Thread.sleep(50));
assertAll("Calculator Operations",
() -> assertEquals(8, calculator.add(5, 3)),
() -> assertEquals(2, calculator.subtract(5, 3))
);assertEquals checks value equality; assertSame checks reference identityassertAll groups multiple assertions so all run even if one fails@ParameterizedTest(name = "{0} + {1} = {2}")
@CsvSource({
"1, 2, 3",
"5, 7, 12",
"-5, 5, 0"
})
void testAdditionWithCsvSource(int a, int b, int expected) {
assertEquals(expected, new Calculator().add(a, b));
}
@ParameterizedTest
@MethodSource("factorialProvider")
void testFactorial(int input, int expected) {
assertEquals(expected, new Calculator().factorial(input));
}
static Stream<Arguments> factorialProvider() {
return Stream.of(Arguments.of(0, 1), Arguments.of(5, 120));
}@CsvSource inlines test data; @MethodSource pulls it from a static factory method@RepeatedTest(value = 5, name = "Repetition {currentRepetition} of {totalRepetitions}")
void testAdditionCommutative() {
int a = random.nextInt(100), b = random.nextInt(100);
assertEquals(calculator.add(a, b), calculator.add(b, a));
}@RepeatedTest(n) reruns a test n times, useful for randomized/property-style checks@TestMethodOrder(MethodOrderer.OrderAnnotation.class) plus @Order(n) on each @Test forces a specific execution order (tests are independent by default, use sparingly)<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>mvn test · Gradle: gradle test (with useJUnitPlatform() configured)JUnit 5 = Platform (TestEngine API) + Jupiter (new annotations/model) + Vintage (JUnit 3/JUnit 4 compatibility)@BeforeAll/@BeforeEach/@AfterEach/@AfterAll) wrap every test with consistent setup and teardown@ParameterizedTest (@CsvSource, @MethodSource) and @RepeatedTest multiply coverage from a single test methodassertEquals, assertThrows, assertAll, assertTimeout) express precise expected behaviorMahmoud Abas|Lab 4: Unit Testing with Java and JUnit 5