[!NOTE] If you build an ecommerce banking application, how do you know the "Calculate Interest" function actually works? Do you manually spin the app up, click 50 buttons, input numbers, and check the math yourself? What if someone breaks the function a month from now?
Professional engineers don't test manually. They write code that automatically tests their code. The industry standard framework for this is JUnit.
What is Unit Testing?
A unit is the absolute smallest piece of testable logic in an application—usually a single method.
Imagine you have a straightforward math class:
public class FinancialMath {
public int calculateTax(int revenue, int deductions) {
if(deductions > revenue) return 0;
return (revenue - deductions) * 20 / 100; // 20% tax rate
}
}
Writing Your First JUnit Test
You create a completely entirely separate file (usually in a /test or /test/java directory).
You annotate methods with @Test. When you click "Run Tests", the IDE executes these methods and uses Assert.assertEquals() to guarantee the output matches what you theoretically expect.
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FinancialMathTest {
// 1. Decorate with the Test runner tag!
@Test
public void testStandardTaxProcessing() {
FinancialMath mathSystem = new FinancialMath();
// 2. Perform the action
int result = mathSystem.calculateTax(1000, 200);
// 800 taxable amount * 20% = 160 expected!
// 3. ASSERTION! (Expected Output vs Reality)
// If 'result' is anything other than 160, the JVM flags this build as FAILED RED!
assertEquals(160, result, "Basic math calculation failed!");
}
@Test
public void testMassiveDeductionsEdgeCase() {
FinancialMath mathSystem = new FinancialMath();
// Test an edge case where a user tries to glitch the system with negative taxes
int result = mathSystem.calculateTax(500, 9999);
// The business rule states output should hard floor to 0!
assertEquals(0, result, "Floor mechanism failed! Issued negative tax!");
}
}
Test-Driven Development (TDD)
Advanced teams use TDD. This means they actually write the JUnit test before they even write the FinancialMath class!
- Write the JUnit test for a theoretical tax method.
- Run it. It fails violently (Red).
- Switch files and write the Java implementation code specifically aiming to make the test Green.
- Run it again. Success (Green)!
- Refactor the code to be cleaner, knowing the safety net of the Green test is guarding you.
[!IMPORTANT] Congratulations! You have completed the epic 40-chapter journey of mastering the JVM. From writing your very first
public static void mainstatement, all the way to Thread Pools, HashMaps, Spring Boot API Servers, and JUnit pipelines. You are officially ready to embark on a career in backend engineering.
Good Tests Check Behavior, Not Implementation
A useful unit test describes what the code should do from the outside. It should not depend too heavily on private helper methods or internal steps. That way, you can refactor implementation without rewriting every test.
Arrange, Act, Assert
@Test
void calculatesDiscountedPrice() {
// Arrange
PricingService service = new PricingService();
// Act
double result = service.applyDiscount(1000, 10);
// Assert
assertEquals(900, result);
}
Test Edge Cases
- Normal valid input.
- Minimum and maximum values.
- Empty input.
- Invalid input.
- Boundary values such as exactly passing marks.
Common Mistakes
- Writing tests that only cover the happy path.
- Putting multiple unrelated behaviors into one test.
- Depending on test execution order.
- Making tests slow by touching real external services unnecessarily.
Mini Practice
Write tests for a isPassing(mark) method. Cover marks 39, 40, 100, and an invalid negative mark.
Practice Lab: Test Passing Marks
Write small tests around behavior and edge cases.
- Create a method
isPassing(int mark). - Write a JUnit test for mark
39. - Write a test for mark
40. - Write a test for mark
100. - Decide what should happen for negative marks and test that behavior.
Goal: Practice boundary-value testing, not only happy-path testing.
Revision Checkpoint
- Unit test: Tests a small piece of behavior.
@Test: Marks a test method.- Assertion: Compares expected result with actual result.
- AAA: Arrange, Act, Assert.
- Edge cases: Test boundaries, invalid input, and normal input.
Before the quiz: Name three test cases for a passing-marks method.