CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-junit--junit

JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.

Overview
Eval results
Files

annotations.mddocs/

Test Annotations

Annotations are the primary mechanism in JUnit 4 for marking test methods and controlling test execution lifecycle. They provide a declarative way to define test structure, setup and teardown procedures, test execution rules, and method ordering.

Capabilities

Test Annotation

Marks a method as a test method. The test method will be executed by the JUnit runner. Supports optional expected parameter for exception testing and timeout parameter for performance testing.

/**
 * Marks a method as a test method
 * @param expected - Optional: the exception class that the test is expected to throw
 * @param timeout - Optional: timeout in milliseconds, test fails if it runs longer
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test {
    Class<? extends Throwable> expected() default None.class;
    long timeout() default 0L;
}

Usage Examples:

import org.junit.Test;
import static org.junit.Assert.*;

public class BasicTest {
    @Test
    public void simpleTest() {
        assertEquals(4, 2 + 2);
    }

    @Test(expected = IllegalArgumentException.class)
    public void testException() {
        throw new IllegalArgumentException("Expected exception");
    }

    @Test(timeout = 1000)
    public void testTimeout() {
        // Test fails if this takes more than 1 second
        performQuickOperation();
    }
}

Before Annotation

Marks a method to run before each test method in the class. Use for test setup that needs to be fresh for each test. The method must be public void with no parameters.

/**
 * Marks a method to run before each test method
 * The annotated method must be public, void, and take no parameters
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Before {}

Usage Examples:

import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;

public class ListTest {
    private List<String> list;

    @Before
    public void setUp() {
        list = new ArrayList<>();
        list.add("initial");
    }

    @Test
    public void testListSize() {
        assertEquals(1, list.size());
    }

    @Test
    public void testListAdd() {
        list.add("second");
        assertEquals(2, list.size());
    }
}

After Annotation

Marks a method to run after each test method in the class. Use for test cleanup and resource disposal. Runs even if the test or @Before method throws an exception.

/**
 * Marks a method to run after each test method
 * The annotated method must be public, void, and take no parameters
 * Runs even if the test or @Before method fails
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface After {}

Usage Examples:

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class FileTest {
    private File tempFile;

    @Before
    public void createFile() throws IOException {
        tempFile = File.createTempFile("test", ".txt");
    }

    @Test
    public void testFileWrite() throws IOException {
        FileWriter writer = new FileWriter(tempFile);
        writer.write("test data");
        writer.close();
        assertTrue(tempFile.length() > 0);
    }

    @After
    public void cleanup() {
        if (tempFile != null && tempFile.exists()) {
            tempFile.delete();
        }
    }
}

BeforeClass Annotation

Marks a static method to run once before all test methods in the class. Use for expensive setup that can be shared across tests. The method must be public static void with no parameters.

/**
 * Marks a static method to run once before all test methods in the class
 * The annotated method must be public, static, void, and take no parameters
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface BeforeClass {}

Usage Examples:

import org.junit.BeforeClass;
import org.junit.Test;
import java.sql.Connection;
import java.sql.DriverManager;

public class DatabaseTest {
    private static Connection connection;

    @BeforeClass
    public static void connectToDatabase() throws Exception {
        // Expensive operation done once for all tests
        connection = DriverManager.getConnection("jdbc:h2:mem:test");
        connection.createStatement().execute("CREATE TABLE users (id INT, name VARCHAR(255))");
    }

    @Test
    public void testInsert() throws Exception {
        connection.createStatement().execute("INSERT INTO users VALUES (1, 'Alice')");
    }

    @Test
    public void testQuery() throws Exception {
        // Connection is already established
        var result = connection.createStatement().executeQuery("SELECT COUNT(*) FROM users");
        assertTrue(result.next());
    }
}

AfterClass Annotation

Marks a static method to run once after all test methods in the class. Use for cleanup of resources established in @BeforeClass. Runs even if tests fail.

/**
 * Marks a static method to run once after all test methods in the class
 * The annotated method must be public, static, void, and take no parameters
 * Runs even if tests or @BeforeClass method fail
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AfterClass {}

Usage Examples:

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class ResourceTest {
    private static ExpensiveResource resource;

    @BeforeClass
    public static void setUp() {
        resource = new ExpensiveResource();
        resource.initialize();
    }

    @Test
    public void testOperation1() {
        resource.performOperation();
    }

    @Test
    public void testOperation2() {
        resource.performAnotherOperation();
    }

    @AfterClass
    public static void tearDown() {
        if (resource != null) {
            resource.cleanup();
            resource = null;
        }
    }
}

Ignore Annotation

Marks a test method or test class to be ignored (not executed). Useful for temporarily disabling tests without deleting them. Can include an optional message explaining why the test is ignored.

/**
 * Marks a test method or test class to be ignored
 * @param value - Optional message explaining why the test is ignored
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Ignore {
    String value() default "";
}

Usage Examples:

import org.junit.Ignore;
import org.junit.Test;

public class FeatureTest {
    @Test
    public void testWorkingFeature() {
        // This test runs normally
        assertTrue(true);
    }

    @Test
    @Ignore("Feature not yet implemented")
    public void testNewFeature() {
        // This test is skipped
        implementNewFeature();
    }

    @Test
    @Ignore
    public void testBrokenFeature() {
        // This test is skipped without a message
        brokenFunction();
    }
}

// Ignore entire test class
@Ignore("Deprecated functionality, will be removed")
public class LegacyTest {
    @Test
    public void test1() {
        // All tests in this class are ignored
    }

    @Test
    public void test2() {
        // This is also ignored
    }
}

Rule Annotation

Marks a field or method that returns a TestRule to be applied to each test method. Rules add behavior around test execution such as timeout enforcement, exception handling, or resource management.

/**
 * Marks a field or method that returns a TestRule
 * The field must be public and of type TestRule or MethodRule
 * If a method, it must be public and return TestRule or MethodRule
 * @param order - Optional order for rule execution (default -1)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface Rule {
    int order() default -1;
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.rules.Timeout;
import java.io.File;
import java.io.IOException;

public class RuleTest {
    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Rule
    public Timeout globalTimeout = Timeout.seconds(10);

    @Test
    public void testUsingTempFolder() throws IOException {
        File file = folder.newFile("test.txt");
        assertTrue(file.exists());
        // File automatically deleted after test
    }

    @Test
    public void testWithTimeout() {
        // This test must complete within 10 seconds
        performOperation();
    }
}

ClassRule Annotation

Marks a static field or method that returns a TestRule to be applied once for the entire test class. Useful for expensive setup that should be shared across all tests.

/**
 * Marks a static field or method that returns a TestRule for the entire class
 * The field must be public static and of type TestRule
 * If a method, it must be public static and return TestRule
 * @param order - Optional order for rule execution (default -1)
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface ClassRule {
    int order() default -1;
}

Usage Examples:

import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.ExternalResource;
import org.junit.rules.TemporaryFolder;

public class ClassRuleTest {
    @ClassRule
    public static TemporaryFolder folder = new TemporaryFolder();

    @ClassRule
    public static ExternalResource resource = new ExternalResource() {
        @Override
        protected void before() throws Throwable {
            // Setup once for all tests
            System.out.println("Starting test class");
        }

        @Override
        protected void after() {
            // Cleanup once after all tests
            System.out.println("Finished test class");
        }
    };

    @Test
    public void test1() {
        // Both rules are applied
    }

    @Test
    public void test2() {
        // Same rule instances used
    }
}

FixMethodOrder Annotation

Specifies the order in which test methods in a class should be executed. By default, JUnit executes methods in an unpredictable order for test isolation.

/**
 * Specifies the execution order for test methods in a class
 * @param value - The ordering strategy to use
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FixMethodOrder {
    MethodSorters value();
}

Usage Examples:

import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OrderedTest {
    @Test
    public void test1_first() {
        System.out.println("Runs first (alphabetically)");
    }

    @Test
    public void test2_second() {
        System.out.println("Runs second");
    }

    @Test
    public void test3_third() {
        System.out.println("Runs third");
    }
}

@FixMethodOrder(MethodSorters.JVM)
public class JvmOrderTest {
    // Tests run in JVM-returned order (varies by JVM)
    @Test
    public void testA() {}

    @Test
    public void testB() {}
}

RunWith Annotation

Specifies a custom runner class to execute the tests instead of the default JUnit 4 runner. Essential for using alternative runners like Suite, Parameterized, or Theories.

/**
 * Specifies a custom runner class for executing tests
 * @param value - The Runner class to use
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface RunWith {
    Class<? extends Runner> value();
}

Usage Examples:

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.junit.runners.Parameterized;
import org.junit.Test;

// Using Suite runner
@RunWith(Suite.class)
@SuiteClasses({TestClass1.class, TestClass2.class, TestClass3.class})
public class AllTests {
    // Runs all tests from the specified classes
}

// Using Parameterized runner
@RunWith(Parameterized.class)
public class FibonacciTest {
    @Parameterized.Parameter(0)
    public int input;

    @Parameterized.Parameter(1)
    public int expected;

    @Parameterized.Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
            {0, 0}, {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}
        });
    }

    @Test
    public void testFibonacci() {
        assertEquals(expected, Fibonacci.compute(input));
    }
}

ValidateWith Annotation

Allows for a custom validator to be attached to an annotation. When attached to an annotation, the validator will be instantiated and invoked by the test runner.

/**
 * Attaches an AnnotationValidator to an annotation
 * @param value - The AnnotationValidator class to use
 * @since 4.12
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
@Inherited
public @interface ValidateWith {
    Class<? extends AnnotationValidator> value();
}

/**
 * Validates annotations on classes, methods, and fields.
 * Instances must be immutable and thread-safe as they are shared by multiple test runners.
 * @since 4.12
 */
public abstract class AnnotationValidator {
    /**
     * Validates annotation on the given class
     * @param testClass - Class being validated
     * @return List of validation exceptions (empty if valid)
     */
    public List<Exception> validateAnnotatedClass(TestClass testClass);

    /**
     * Validates annotation on the given field
     * @param field - Field being validated
     * @return List of validation exceptions (empty if valid)
     */
    public List<Exception> validateAnnotatedField(FrameworkField field);

    /**
     * Validates annotation on the given method
     * @param method - Method being validated
     * @return List of validation exceptions (empty if valid)
     */
    public List<Exception> validateAnnotatedMethod(FrameworkMethod method);
}

Usage Examples:

import org.junit.validator.ValidateWith;
import org.junit.validator.AnnotationValidator;
import org.junit.runners.model.TestClass;

import java.lang.annotation.*;
import java.util.ArrayList;
import java.util.List;

// Define custom annotation with validator
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ValidateWith(RequiresJava8Validator.class)
public @interface RequiresJava8 {}

// Implement the validator
public class RequiresJava8Validator extends AnnotationValidator {
    @Override
    public List<Exception> validateAnnotatedClass(TestClass testClass) {
        List<Exception> errors = new ArrayList<>();
        String javaVersion = System.getProperty("java.version");
        if (!javaVersion.startsWith("1.8") && !javaVersion.startsWith("8")) {
            errors.add(new Exception(
                "Test requires Java 8 but running on " + javaVersion));
        }
        return errors;
    }
}

// Use the validated annotation
@RequiresJava8
public class Java8OnlyTest {
    @Test
    public void testStreamApi() {
        // Test will only run on Java 8+
    }
}

OrderWith Annotation

Specifies a custom ordering for test methods. Allows fine-grained control over test execution order beyond the basic alphabetical or JVM ordering.

/**
 * Specifies an ordering for test methods
 * @param value - The Ordering.Factory class to use
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
@ValidateWith(OrderWithValidator.class)
public @interface OrderWith {
    Class<? extends Ordering.Factory> value();
}

Usage Examples:

import org.junit.runner.OrderWith;
import org.junit.runner.manipulation.Alphanumeric;
import org.junit.Test;

@OrderWith(Alphanumeric.class)
public class CustomOrderedTest {
    @Test
    public void testA() {
        // Tests run in alphanumeric order
        System.out.println("Test A");
    }

    @Test
    public void testB() {
        System.out.println("Test B");
    }
}

Types

/**
 * Method ordering strategies for @FixMethodOrder
 */
public enum MethodSorters {
    /**
     * Sorts methods by method name, in lexicographic order
     */
    NAME_ASCENDING,

    /**
     * Leaves test methods in order returned by JVM (may vary)
     */
    JVM,

    /**
     * Default - pseudo-random order that changes between runs
     */
    DEFAULT
}

/**
 * Placeholder class for @Test annotation's default expected value
 */
public class None extends Throwable {
    private None() {}
}

Install with Tessl CLI

npx tessl i tessl/maven-junit--junit

docs

annotations.md

assertions.md

assumptions.md

categories.md

index.md

matchers.md

rules.md

standard-runners.md

test-runners.md

theories.md

tile.json