JUnit Testing
Fast recall
Quick revision
Core answer
@Test, lifecycle callbacks, parameterized tests, assertions, and an extension API; the JUnit Platform discovers and launches test engines. It turns expected behavior into repeatable automated checks that can run in an IDE or build, giving earlier feedback and regression evidence within the scenarios the tests cover.Interview-ready guide
Interview answer
JUnit is the standard unit-testing framework for Java.
It provides annotations like @Test, @BeforeEach, and @AfterEach to mark test methods and lifecycle hooks, assertion methods like assertEquals and assertThrows to verify expected behavior, and a test runner that executes everything and reports pass or fail. It exists because manual testing does not scale and because without automated tests, refactoring becomes risky -- you are afraid to touch working code because you cannot verify it still works.
A good unit test follows the AAA pattern: Arrange the preconditions, Act by calling the method, and Assert the outcome. I write each test to verify a single behavior, use parameterized tests to cover multiple inputs without duplication, and rely on Mockito to isolate the unit from its dependencies. In JUnit 5, I particularly like assertThrows for exception testing and the extension model for composable test setup.
JUnit Testing
Direct Answer
JUnit is a widely used Java testing framework. JUnit Jupiter provides annotations such as @Test, lifecycle callbacks, parameterized tests, assertions, and an extension API; the JUnit Platform discovers and launches test engines. It turns expected behavior into repeatable automated checks that can run in an IDE or build, giving earlier feedback and regression evidence within the scenarios the tests cover.
Code Example
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator = new Calculator(); // fresh instance per test
}
@Test
@DisplayName("Adding two positive numbers returns correct sum")
void testAdd() {
// Arrange -- Act -- Assert
int result = calculator.add(3, 7);
assertEquals(10, result, "3 + 7 should equal 10");
}
@Test
@DisplayName("Division by zero throws ArithmeticException")
void testDivideByZero() {
assertThrows(ArithmeticException.class,
() -> calculator.divide(10, 0));
}
@ParameterizedTest
@ValueSource(ints = {1, 2, 3, 4, 5})
@DisplayName("Positive numbers return true from isPositive")
void testIsPositive(int value) {
assertTrue(calculator.isPositive(value));
}
@AfterEach
void tearDown() {
calculator = null; // cleanup after each test
}
}
Check your understanding
Answer these without looking back at the article.
- What is the difference between @BeforeEach and @BeforeAll in JUnit 5?
- How do parameterized tests work in JUnit 5?
- What is the AAA pattern in unit testing?
- How does Mockito integrate with JUnit for mocking dependencies?
- What is the test pyramid and why should unit tests outnumber integration tests?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.