Day 7: JUnit

It is 15 minutes to 10 in the morning dated 12th of June. I have been dilly-dallying a lot, so let’s just get to it!
JUnit Basics
Concept | Description |
What is JUnit? | A Java framework for writing and running unit tests. |
Unit Test | Tests a single unit of code (usually a method) in isolation. |
Test Lifecycle | Each test runs in a fresh instance of the test class by default. |
Annotations
Annotation | Purpose |
@Test | Marks a method as a test method. |
@BeforeEach | Runs before each test (setup). |
@AfterEach | Runs after each test (cleanup). |
@BeforeAll | Runs once before all tests (static method). |
@AfterAll | Runs once after all tests (static method). |
@DisplayName("...") | Gives a custom name to a test method. |
@Disabled | Skips a test method/class. |
@Nested | Groups tests logically in inner classes. |
Assertions
Assertions check if the code behaves as expected.
Assertion | Meaning |
assertEquals(expected, actual) | Checks if two values are equal. |
assertNotEquals(a, b) | Checks if two values are not equal. |
assertTrue(condition) | Checks if condition is true. |
assertFalse(condition) | Checks if condition is false. |
assertNull(value) | Checks if the value is null. |
assertNotNull(value) | Checks if the value is not null. |
assertThrows() | Verifies an exception is thrown. |
assertAll() | Runs multiple assertions in one go. |
assertTimeout() | Fails if execution exceeds time limit. |
Example Program
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator();
}
@Test
@DisplayName("Addition should return correct result")
void testAddition() {
assertEquals(5, calculator.add(2, 3));
assertNotEquals(6, calculator.add(2, 3));
}
@Test
@DisplayName("Division by zero should throw exception")
void testDivideByZero() {
assertThrows(ArithmeticException.class, () -> calculator.divide(10, 0));
}
@AfterEach
void tearDown() {
calculator = null;
}
}
class Calculator {
int add(int a, int b) {
return a + b;
}
int divide(int a, int b) {
return a / b;
}
}
We observe:
We are testing each method of class Calculator - add & divide which are our units.
Tests are defined by the annotation
@Test
@BeforeEach runs before each tests are executed and is used to establish any connections or for other configurations.
In a similar sense, @AfterEach runs after each test, closing up the resources.
assertEquals and assertNotEquals checks if the expected result and the actual result are equal or not equal respectively.
assertThrows checks if the exception - ArithmeticException is thrown or not.
Remember: Each test method creates a different CalculatorTest Object. You can use this annotation above the class -
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
to use the same test object throughout all test cases.
Parameterized Tests
@ParameterizedTest
@CsvSource({
"2, 3, 5",
"10, 20, 30",
"-5, 5, 0"
})
void testAddition(int a, int b, int expected) {
assertEquals(expected, new Calculator().add(a, b));
}
Grouped Assertions
@Test
void testUserProfile() {
User user = new User("Alice", 25);
assertAll("user",
() -> assertEquals("Alice", user.getName()),
() -> assertTrue(user.getAge() > 18),
() -> assertNotNull(user.getId()) // Assume id is auto-generated
);
}
Timeout Assertions
@Test
void testWithTimeout() {
assertTimeout(Duration.ofMillis(100), () -> {
Thread.sleep(50); // Will pass
});
}
That’s it for JUnit 5, we will be looking at Git in our next adventure!
Stay tuned and keep supporting our party!
Subscribe to my newsletter
Read articles from Nagraj Math directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
