Testing and Debugging in Java
๐ก Intermediate
๐ Definition
- Unit Testing: Automating the verification of individual units of code (like isolated methods or classes) using frameworks such as JUnit 5 (Jupiter).
- Debugging: Isolating, inspecting, and fixing runtime errors, logical bugs, and exceptions using IDE breakpoints, stack trace inspection, and variable watches.
๐ฎ๐ณ Hindi
Software quality maintain karne ke liye JUnit 5 test framework se automated unit tests likhe jaate hain. Runtime bugs fix karne ke liye IDE breakpoints, stack trace inspection, aur variable inspection ka use karke line-by-line execution debug kiya jata hai.
๐ฉ Marathi
Automated tests sathi JUnit 5 framework vaparatat. Code madhil bugs shodhnyasathi IDE Breakpoints aani Debugger vaparatat.
๐ 1. Core JUnit 5 Test Annotations
| Annotation | What It Does |
|---|---|
@Test |
Marks a method as an automated test case |
@BeforeEach |
Executes before each @Test method in the test class |
@AfterEach |
Executes after each @Test method |
@BeforeAll |
Executes once before all tests in class (static) |
@AfterAll |
Executes once after all tests in class (static) |
@DisplayName("Custom Name") |
Declares a readable custom test title |
@Disabled |
Skips execution of test method |
๐ 2. JUnit 5 Assertions
import static org.junit.jupiter.api.Assertions.*;
assertEquals(expected, actual);
assertTrue(condition);
assertFalse(condition);
assertNull(objectReference);
assertNotNull(objectReference);
// Exception Assertion (Verifies specific exception is thrown)
assertThrows(IllegalArgumentException.class, () -> {
methodThatShouldThrow();
});
๐ 3. Effective IDE Debugging Strategies
- Set Breakpoint: Click on any line margin in IntelliJ IDEA or VS Code to pause execution when reached.
- Inspect Variables: View current field values in heap memory in the debugger scope window.
- Control Stepping:
- Step Over (F8): Executes current line and moves to next line.
- Step Into (F7): Jumps inside called method.
- Step Out (Shift+F8): Finishes current method and returns to caller.
- Resume (F9): Resumes normal execution until next breakpoint.
๐ก Complete Example: Class & Unit Test Class
Class to Test: CalculatorService.java
public class CalculatorService {
public double divide(double numerator, double denominator) {
if (denominator == 0.0) {
throw new ArithmeticException("Division by zero is not allowed.");
}
return numerator / denominator;
}
public boolean isEven(int number) {
return number % 2 == 0;
}
}
Automated Unit Test: CalculatorServiceTest.java
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
@DisplayName("Calculator Service Unit Tests")
public class CalculatorServiceTest {
private CalculatorService calculator;
@BeforeEach
void setUp() {
calculator = new CalculatorService(); // Re-instantiated before each test
}
@Test
@DisplayName("Should divide two valid numbers correctly")
void testValidDivision() {
double result = calculator.divide(10.0, 2.0);
assertEquals(5.0, result, 0.0001, "10 / 2 should equal 5.0");
}
@Test
@DisplayName("Should throw ArithmeticException when dividing by zero")
void testDivisionByZeroThrowsException() {
Exception exception = assertThrows(ArithmeticException.class, () -> {
calculator.divide(10.0, 0.0);
});
assertEquals("Division by zero is not allowed.", exception.getMessage());
}
@Test
@DisplayName("Should correctly identify even numbers")
void testIsEven() {
assertTrue(calculator.isEven(4));
assertFalse(calculator.isEven(7));
}
}
๐ Test Execution Output
JUnit Jupiter Test Runner Execution
-------------------------------------------------------
[โ] Calculator Service Unit Tests
[โ] Should divide two valid numbers correctly
[โ] Should throw ArithmeticException when dividing by zero
[โ] Should correctly identify even numbers
Tests passed: 3 of 3 (100% SUCCESS)
-------------------------------------------------------
โ ๏ธ Common Mistakes
- Writing unit tests that depend on each otherโs execution order or shared mutable global state.
- Asserting only happy-path inputs while ignoring edge cases and boundary conditions (e.g.
null,0, negative values). - Reading only the bottom line of an error stack trace; always look for the first relevant line number in your own package code!
๐ก๏ธ Safety / Important Notes
Keep unit tests fast, isolated, repeatable, and independent so they can run automatically during continuous integration build pipelines (mvn test).
๐ Real-World Usage
CI/CD deployment pipelines (GitHub Actions, Jenkins), regression testing during codebase refactoring, and verifying business validation rules.
๐งช Try It Yourself
- Create a
BankAccountclass withdeposit()andwithdraw()methods. - Write a JUnit test class verifying that withdrawing more than balance throws
IllegalArgumentException.
๐ฏ Mini Challenge
Write a JUnit test verifying that a custom string reverse method returns "" when passed "" and correctly handles null arguments by throwing NullPointerException.
๐ Related Topics
๐งญ Navigation
| โ Java Home | โ Previous: Dates and Time | Next: Build Tools and Mini Projects โ |