JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
npx @tessl/cli install tessl/maven-junit--junit@4.13.0JUnit 4 is a widely-used unit testing framework for Java, created by Erich Gamma and Kent Beck. It provides a comprehensive set of annotations, assertions, and runners for writing and executing automated tests. JUnit 4 uses annotations to mark test methods and control test execution, making it simple to create well-structured test suites.
Maven:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>Gradle:
testImplementation 'junit:junit:4.13.2'import org.junit.Test;
import org.junit.Before;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Ignore;
import static org.junit.Assert.*;For running tests:
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;For rules:
import org.junit.Rule;
import org.junit.ClassRule;
import org.junit.rules.*;import org.junit.*;
import static org.junit.Assert.*;
public class CalculatorTest {
private Calculator calculator;
@BeforeClass
public static void setUpClass() {
System.out.println("Running Calculator tests");
}
@Before
public void setUp() {
calculator = new Calculator();
}
@Test
public void testAddition() {
assertEquals(5, calculator.add(2, 3));
}
@Test
public void testSubtraction() {
assertEquals(1, calculator.subtract(3, 2));
}
@Test(expected = ArithmeticException.class)
public void testDivisionByZero() {
calculator.divide(10, 0);
}
@Test(timeout = 1000)
public void testPerformance() {
calculator.complexCalculation();
}
@After
public void tearDown() {
calculator = null;
}
@AfterClass
public static void tearDownClass() {
System.out.println("Calculator tests complete");
}
}JUnit 4's architecture is built around several key components:
@Test, @Before, @After, etc.) that define test structure and lifecycleAssert class for verifying expected behaviorBlockJUnit4ClassRunner processes annotated test classes, while custom runners like Suite and Parameterized enable advanced scenarios@Rule, @ClassRule) that add behavior around test methods, such as temporary file creation or timeout enforcement@BeforeClass and @AfterClass run once per test class, while @Before and @After run before and after each test methodResult class collects test outcomes, failures, and timing informationThis design allows JUnit to provide a flexible, extensible framework for Java testing while maintaining simplicity for common use cases.
Declarative annotations for marking test methods and controlling test execution lifecycle. These annotations define which methods are tests, how they should be executed, and what setup/teardown is required.
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {
Class<? extends Throwable> expected() default None.class;
long timeout() default 0L;
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Before {}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface After {}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface BeforeClass {}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AfterClass {}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ignore {
String value() default "";
}Comprehensive assertion methods for verifying expected behavior in tests. The Assert class provides static methods for comparing values, checking conditions, and validating object states.
public class Assert {
public static void assertEquals(String message, Object expected, Object actual);
public static void assertEquals(Object expected, Object actual);
public static void assertTrue(String message, boolean condition);
public static void assertTrue(boolean condition);
public static void assertFalse(String message, boolean condition);
public static void assertFalse(boolean condition);
public static void assertNull(String message, Object object);
public static void assertNull(Object object);
public static void assertNotNull(String message, Object object);
public static void assertNotNull(Object object);
public static void assertSame(String message, Object expected, Object actual);
public static void assertSame(Object expected, Object actual);
public static void assertNotSame(String message, Object unexpected, Object actual);
public static void assertNotSame(Object unexpected, Object actual);
public static void assertArrayEquals(String message, Object[] expecteds, Object[] actuals);
public static void assertArrayEquals(Object[] expecteds, Object[] actuals);
public static <T extends Throwable> T assertThrows(Class<T> expectedThrowable, ThrowingRunnable runnable);
public static void fail(String message);
public static void fail();
}Methods for conditionally skipping tests based on runtime conditions. When an assumption fails, the test is marked as skipped rather than failed, useful for environment-specific tests.
public class Assume {
public static void assumeTrue(boolean condition);
public static void assumeTrue(String message, boolean condition);
public static void assumeFalse(boolean condition);
public static void assumeFalse(String message, boolean condition);
public static void assumeNotNull(Object... objects);
public static <T> void assumeThat(T actual, Matcher<T> matcher);
public static void assumeNoException(Throwable t);
}Core classes for executing tests and collecting results. JUnitCore provides the main API for running tests programmatically, while the Runner class hierarchy enables custom test execution strategies.
public class JUnitCore {
public static void main(String... args);
public Result run(Class<?>... classes);
public Result run(Request request);
public Result runClasses(Class<?>... classes);
public void addListener(RunListener listener);
public void removeListener(RunListener listener);
}
public abstract class Runner implements Describable {
public abstract Description getDescription();
public abstract void run(RunNotifier notifier);
public int testCount();
}
public class Result {
public int getRunCount();
public int getFailureCount();
public int getIgnoreCount();
public long getRunTime();
public List<Failure> getFailures();
public boolean wasSuccessful();
}Built-in test runners for common scenarios including the standard JUnit 4 runner, test suites, and parameterized tests that run the same test with different data.
public class BlockJUnit4ClassRunner extends ParentRunner<FrameworkMethod> {
public BlockJUnit4ClassRunner(Class<?> testClass) throws InitializationError;
}
public class Suite extends ParentRunner<Runner> {
public Suite(Class<?> klass, Class<?>[] suiteClasses) throws InitializationError;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SuiteClasses {
Class<?>[] value();
}
}
public class Parameterized extends Suite {
public Parameterized(Class<?> klass) throws Throwable;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Parameters {
String name() default "{index}";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Parameter {
int value() default 0;
}
}The rule system provides reusable test behavior that can be applied to test methods or entire test classes. Rules wrap test execution with custom logic for resource management, verification, and more.
public interface TestRule {
Statement apply(Statement base, Description description);
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Rule {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface ClassRule {}Experimental feature for grouping and filtering tests by category markers. Allows selective test execution based on custom category interfaces.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Category {
Class<?>[] value();
}
public class Categories extends Suite {
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface IncludeCategory {
Class<?> value();
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ExcludeCategory {
Class<?> value();
}
}Experimental feature for property-based testing where tests are theories proven against multiple data points. Theories are parameterized tests with data point injection.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Theory {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface DataPoint {
String[] value() default {};
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface DataPoints {
String[] value() default {};
}
public class Theories extends BlockJUnit4ClassRunner {
public Theories(Class<?> klass) throws InitializationError;
}Integration with Hamcrest matchers for expressive assertions. Matchers provide readable, composable conditions for test verification.
public class Assert {
public static <T> void assertThat(T actual, Matcher<? super T> matcher);
public static <T> void assertThat(String reason, T actual, Matcher<? super T> matcher);
}
public class JUnitMatchers {
public static Matcher<String> containsString(String substring);
public static <T> CombinableBothMatcher<T> both(Matcher<? super T> matcher);
public static <T> CombinableEitherMatcher<T> either(Matcher<? super T> matcher);
public static <T extends Throwable> Matcher<T> isThrowable(Matcher<T> causeMatcher);
public static <T extends Exception> Matcher<T> isException(Matcher<T> causeMatcher);
}@FunctionalInterface
public interface ThrowingRunnable {
void run() throws Throwable;
}
public class Description implements Serializable {
// Constants
public static final Description EMPTY;
public static final Description TEST_MECHANISM;
// Factory methods for test descriptions
public static Description createTestDescription(String className, String name, Annotation... annotations);
public static Description createTestDescription(String className, String name, Serializable uniqueId);
public static Description createTestDescription(Class<?> clazz, String name);
public static Description createTestDescription(Class<?> clazz, String name, Annotation... annotations);
// Factory methods for suite descriptions
public static Description createSuiteDescription(String name, Annotation... annotations);
public static Description createSuiteDescription(String name, Serializable uniqueId, Annotation... annotations);
public static Description createSuiteDescription(Class<?> testClass);
public static Description createSuiteDescription(Class<?> testClass, Annotation... annotations);
// Naming methods
public String getClassName();
public String getMethodName();
public String getDisplayName();
// Type checking
public boolean isTest();
public boolean isSuite();
public boolean isEmpty();
// Children management
public void addChild(Description description);
public ArrayList<Description> getChildren();
public Description childlessCopy();
// Counting
public int testCount();
// Annotations
public <T extends Annotation> T getAnnotation(Class<T> annotationType);
public Collection<Annotation> getAnnotations();
// Class information
public Class<?> getTestClass();
}
public class Failure implements Serializable {
public Failure(Description description, Throwable thrownException);
public Description getDescription();
public Throwable getException();
public String getMessage();
public String getTrace();
}
public abstract class Statement {
public abstract void evaluate() throws Throwable;
}