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

rules.mddocs/

Rules

Rules provide a way to add reusable behavior around test execution. They can be applied to individual test methods (@Rule) or entire test classes (@ClassRule). Rules are more flexible and composable than inheritance-based approaches.

Capabilities

TestRule Interface

The core interface for implementing custom rules. Rules wrap test execution with custom behavior.

/**
 * Interface for test rules
 * A rule wraps test execution with custom behavior
 */
public interface TestRule {
    /**
     * Modifies the Statement that executes a test
     * @param base - The Statement to be modified
     * @param description - Description of the test
     * @return Modified Statement
     */
    Statement apply(Statement base, Description description);
}

Usage Examples:

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class LoggingRule implements TestRule {
    @Override
    public Statement apply(Statement base, Description description) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                System.out.println("Starting: " + description.getMethodName());
                try {
                    base.evaluate();
                    System.out.println("Passed: " + description.getMethodName());
                } catch (Throwable t) {
                    System.out.println("Failed: " + description.getMethodName());
                    throw t;
                }
            }
        };
    }
}

// Usage
public class MyTest {
    @Rule
    public TestRule loggingRule = new LoggingRule();

    @Test
    public void testSomething() {
        // Logging happens automatically
        assertTrue(true);
    }
}

TemporaryFolder

Creates temporary files and folders that are automatically deleted after the test. Useful for tests that need file system access.

/**
 * Rule for creating temporary files and folders
 * Automatically deleted after test completion
 */
public class TemporaryFolder extends ExternalResource {
    /**
     * Creates a TemporaryFolder using default temp directory
     */
    public TemporaryFolder();

    /**
     * Creates a TemporaryFolder in specified parent folder
     * @param parentFolder - Parent directory for temp folder
     */
    public TemporaryFolder(File parentFolder);

    /**
     * Get the root temporary folder
     * @return Root folder (created lazily)
     */
    public File getRoot();

    /**
     * Create a new temporary file with random name
     * @return Created file
     * @throws IOException if file cannot be created
     */
    public File newFile() throws IOException;

    /**
     * Create a new temporary file with specified name
     * @param filename - Name for the file
     * @return Created file
     * @throws IOException if file cannot be created
     */
    public File newFile(String filename) throws IOException;

    /**
     * Create a new temporary folder with random name
     * @return Created folder
     * @throws IOException if folder cannot be created
     */
    public File newFolder() throws IOException;

    /**
     * Create a new temporary folder with specified name
     * @param folderName - Name for the folder
     * @return Created folder
     * @throws IOException if folder cannot be created
     */
    public File newFolder(String folderName) throws IOException;

    /**
     * Create a new temporary folder with path segments
     * @param folderNames - Path segments for nested folders
     * @return Created folder
     * @throws IOException if folder cannot be created
     */
    public File newFolder(String... folderNames) throws IOException;

    /**
     * Delete all files and folders
     */
    public void delete();

    /**
     * Builder for configuring TemporaryFolder
     */
    public static class Builder {
        public Builder parentFolder(File parentFolder);
        public Builder assureDeletion();
        public TemporaryFolder build();
    }

    public static Builder builder();
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.*;
import static org.junit.Assert.*;

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

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

    @Test
    public void testFileWrite() throws IOException {
        File file = folder.newFile("data.txt");
        FileWriter writer = new FileWriter(file);
        writer.write("Hello, World!");
        writer.close();

        BufferedReader reader = new BufferedReader(new FileReader(file));
        assertEquals("Hello, World!", reader.readLine());
        reader.close();
    }

    @Test
    public void testFolderCreation() throws IOException {
        File subFolder = folder.newFolder("subfolder");
        File nestedFile = new File(subFolder, "nested.txt");
        nestedFile.createNewFile();
        assertTrue(nestedFile.exists());
    }

    @Test
    public void testNestedFolders() throws IOException {
        File nested = folder.newFolder("level1", "level2", "level3");
        assertTrue(nested.exists());
        assertTrue(nested.isDirectory());
    }
}

// Using builder
public class ConfiguredFolderTest {
    @Rule
    public TemporaryFolder folder = TemporaryFolder.builder()
        .parentFolder(new File("/tmp"))
        .assureDeletion()
        .build();
}

ExpectedException

DEPRECATED since JUnit 4.13 - Use Assert.assertThrows() instead.

Verifies that code throws expected exceptions with specific properties. More flexible than @Test(expected=...).

/**
 * Rule for verifying expected exceptions
 * Provides detailed exception matching
 *
 * @deprecated Since 4.13 - Use Assert.assertThrows(Class, ThrowingRunnable) instead
 */
@Deprecated
public class ExpectedException implements TestRule {
    /**
     * Create an ExpectedException rule
     * @return New ExpectedException instance
     * @deprecated Since 4.13 - Use Assert.assertThrows() instead
     */
    @Deprecated
    public static ExpectedException none();

    /**
     * Expect exception of specific type
     * @param type - Expected exception class
     */
    public void expect(Class<? extends Throwable> type);

    /**
     * Expect exception matching a matcher
     * @param matcher - Hamcrest matcher for exception
     */
    public void expect(Matcher<?> matcher);

    /**
     * Expect exception message containing specific text
     * @param substring - Expected substring in message
     */
    public void expectMessage(String substring);

    /**
     * Expect exception message matching a matcher
     * @param matcher - Hamcrest matcher for message
     */
    public void expectMessage(Matcher<String> matcher);

    /**
     * Expect exception cause matching a matcher
     * @param expectedCause - Matcher for cause
     */
    public void expectCause(Matcher<? extends Throwable> expectedCause);

    /**
     * Check if any exception is expected
     * @return true if exception expected
     */
    public boolean isAnyExceptionExpected();

    /**
     * Configure to handle AssertionErrors as exceptions
     * @return This instance for chaining
     */
    public ExpectedException handleAssertionErrors();

    /**
     * Configure to handle AssumptionViolatedExceptions
     * @return This instance for chaining
     */
    public ExpectedException handleAssumptionViolatedExceptions();

    /**
     * Configure custom message for missing exception
     * @param message - Custom message
     * @return This instance for chaining
     */
    public ExpectedException reportMissingExceptionWithMessage(String message);
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import static org.hamcrest.CoreMatchers.*;

public class ExceptionTest {
    @Rule
    public ExpectedException thrown = ExpectedException.none();

    @Test
    public void testExceptionType() {
        thrown.expect(IllegalArgumentException.class);
        throw new IllegalArgumentException("Invalid argument");
    }

    @Test
    public void testExceptionMessage() {
        thrown.expect(NullPointerException.class);
        thrown.expectMessage("Cannot be null");
        processNull(null);
    }

    @Test
    public void testExceptionMessagePattern() {
        thrown.expect(IllegalStateException.class);
        thrown.expectMessage(containsString("invalid state"));
        performInvalidOperation();
    }

    @Test
    public void testExceptionCause() {
        thrown.expect(RuntimeException.class);
        thrown.expectCause(isA(IOException.class));
        throw new RuntimeException("Wrapped", new IOException("IO error"));
    }

    @Test
    public void testMultipleConditions() {
        thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage(startsWith("Invalid"));
        thrown.expectMessage(containsString("parameter"));
        validateParameter(-1);
    }
}

Timeout

Applies a timeout to all test methods in a class. Test fails if it runs longer than specified time.

/**
 * Rule for enforcing test timeouts
 */
public class Timeout implements TestRule {
    /**
     * Create timeout in milliseconds
     * @param millis - Timeout in milliseconds
     * @return Timeout rule
     */
    public static Timeout millis(long millis);

    /**
     * Create timeout in seconds
     * @param seconds - Timeout in seconds
     * @return Timeout rule
     */
    public static Timeout seconds(long seconds);

    /**
     * Get builder for configuring timeout
     * @return Builder instance
     */
    public static Builder builder();

    /**
     * Builder for Timeout configuration
     */
    public static class Builder {
        /**
         * Set timeout duration
         * @param timeout - Timeout value
         * @param unit - Time unit
         * @return This builder
         */
        public Builder withTimeout(long timeout, TimeUnit unit);

        /**
         * Enable looking for stuck threads
         * @param enable - Whether to look for stuck threads
         * @return This builder
         */
        public Builder withLookingForStuckThread(boolean enable);

        /**
         * Build the Timeout rule
         * @return Configured Timeout
         */
        public Timeout build();
    }
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Timeout;
import java.util.concurrent.TimeUnit;

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

    @Test
    public void testFastOperation() {
        // Must complete within 10 seconds
        performQuickOperation();
    }

    @Test
    public void testAnotherOperation() {
        // Also must complete within 10 seconds
        performOperation();
    }
}

// Using builder
public class ConfiguredTimeoutTest {
    @Rule
    public Timeout timeout = Timeout.builder()
        .withTimeout(5, TimeUnit.SECONDS)
        .withLookingForStuckThread(true)
        .build();

    @Test
    public void testWithStuckThreadDetection() {
        performOperation();
    }
}

// Milliseconds timeout
public class MillisTimeoutTest {
    @Rule
    public Timeout timeout = Timeout.millis(500);

    @Test
    public void testVeryFastOperation() {
        // Must complete within 500ms
        quickOperation();
    }
}

TestName

Provides access to the name of the currently executing test method. Useful for debugging and logging.

/**
 * Rule for accessing current test method name
 */
public class TestName extends TestWatcher {
    /**
     * Get the name of the current test method
     * @return Test method name
     */
    public String getMethodName();
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import static org.junit.Assert.*;

public class NamedTest {
    @Rule
    public TestName testName = new TestName();

    @Test
    public void testA() {
        assertEquals("testA", testName.getMethodName());
        System.out.println("Running: " + testName.getMethodName());
    }

    @Test
    public void testB() {
        assertEquals("testB", testName.getMethodName());
    }

    @Test
    public void testWithLogging() {
        String currentTest = testName.getMethodName();
        log("Starting test: " + currentTest);
        performOperation();
        log("Finished test: " + currentTest);
    }
}

ErrorCollector

Collects multiple errors in a single test, allowing the test to continue after failures. Useful for validating multiple conditions.

/**
 * Rule for collecting multiple errors
 * Test continues after failures and reports all errors at end
 */
public class ErrorCollector extends Verifier {
    /**
     * Add an error
     * @param error - Throwable to collect
     */
    public void addError(Throwable error);

    /**
     * Check a condition and collect error if false
     * @param value - Value to check
     * @param matcher - Matcher to apply
     */
    public <T> void checkThat(T value, Matcher<T> matcher);

    /**
     * Check a condition with reason
     * @param reason - Reason for the check
     * @param value - Value to check
     * @param matcher - Matcher to apply
     */
    public <T> void checkThat(String reason, T value, Matcher<T> matcher);

    /**
     * Call a callable and collect errors
     * @param callable - Code to execute
     * @return Result of callable
     */
    public <T> T checkSucceeds(Callable<T> callable);

    /**
     * Check that runnable throws expected exception
     * @param expectedThrowable - Expected exception type
     * @param runnable - Code to execute
     */
    public <T extends Throwable> void checkThrows(
        Class<T> expectedThrowable,
        ThrowingRunnable runnable
    );
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
import static org.hamcrest.CoreMatchers.*;

public class MultipleChecksTest {
    @Rule
    public ErrorCollector collector = new ErrorCollector();

    @Test
    public void testMultipleValues() {
        // All checks are performed even if some fail
        collector.checkThat("First check", 1 + 1, is(2));
        collector.checkThat("Second check", 2 + 2, is(4));
        collector.checkThat("Third check", 3 + 3, is(6));
        // If any fail, all failures are reported together
    }

    @Test
    public void testTableData() {
        int[][] table = getTestData();
        for (int i = 0; i < table.length; i++) {
            for (int j = 0; j < table[i].length; j++) {
                collector.checkThat(
                    "Cell [" + i + "][" + j + "]",
                    table[i][j],
                    greaterThan(0)
                );
            }
        }
        // Reports all failing cells, not just the first one
    }

    @Test
    public void testWithCallable() {
        String result = collector.checkSucceeds(() -> {
            return performOperation();
        });
        assertNotNull(result);
    }
}

ExternalResource

Base class for rules that set up and tear down external resources. Template for resource management.

/**
 * Base class for rules that manage external resources
 */
public abstract class ExternalResource implements TestRule {
    /**
     * Override to set up resource before test
     */
    protected void before() throws Throwable;

    /**
     * Override to tear down resource after test
     */
    protected void after();
}

Usage Examples:

import org.junit.rules.ExternalResource;
import org.junit.Rule;
import org.junit.Test;

public class DatabaseResource extends ExternalResource {
    private Database database;

    @Override
    protected void before() throws Throwable {
        database = new Database();
        database.connect();
        database.initialize();
    }

    @Override
    protected void after() {
        if (database != null) {
            database.disconnect();
        }
    }

    public Database getDatabase() {
        return database;
    }
}

public class DatabaseTest {
    @Rule
    public DatabaseResource dbResource = new DatabaseResource();

    @Test
    public void testQuery() {
        Database db = dbResource.getDatabase();
        Result result = db.query("SELECT * FROM users");
        assertNotNull(result);
    }
}

// Server resource example
public class ServerResource extends ExternalResource {
    private TestServer server;
    private int port;

    public ServerResource(int port) {
        this.port = port;
    }

    @Override
    protected void before() throws Throwable {
        server = new TestServer(port);
        server.start();
    }

    @Override
    protected void after() {
        if (server != null) {
            server.stop();
        }
    }

    public String getUrl() {
        return "http://localhost:" + port;
    }
}

RuleChain

Chains multiple rules to execute in a specific order. Useful when rules have dependencies.

/**
 * Chains multiple rules to execute in order
 */
public class RuleChain implements TestRule {
    /**
     * Create an empty rule chain
     * @return Empty RuleChain
     */
    public static RuleChain emptyRuleChain();

    /**
     * Create a rule chain starting with a rule
     * @param outerRule - First rule in chain
     * @return RuleChain with the rule
     */
    public static RuleChain outerRule(TestRule outerRule);

    /**
     * Add a rule to the chain
     * @param rule - Rule to add
     * @return This RuleChain
     */
    public RuleChain around(TestRule rule);
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.rules.ExternalResource;
import org.junit.rules.TestRule;

public class ChainedRulesTest {
    private DatabaseResource database = new DatabaseResource();
    private ServerResource server = new ServerResource(8080);

    @Rule
    public TestRule chain = RuleChain
        .outerRule(database)      // First: set up database
        .around(server);          // Then: start server (can use database)

    @Test
    public void testWithBothResources() {
        // Both database and server are available
        makeRequestToServer();
    }
}

// More complex chain
public class ComplexChainTest {
    @Rule
    public TestRule chain = RuleChain
        .outerRule(new LoggingRule())
        .around(new TimeoutRule())
        .around(new ResourceRule());

    @Test
    public void test() {
        // Rules execute in order: Logging -> Timeout -> Resource
        // Cleanup happens in reverse: Resource -> Timeout -> Logging
    }
}

TestWatcher

Observes test execution and provides hooks for test lifecycle events. Base class for monitoring rules.

/**
 * Base class for rules that observe test execution
 */
public abstract class TestWatcher implements TestRule {
    /**
     * Called when test succeeds
     * @param description - Test description
     */
    protected void succeeded(Description description);

    /**
     * Called when test fails
     * @param e - Throwable that caused failure
     * @param description - Test description
     */
    protected void failed(Throwable e, Description description);

    /**
     * Called when test is skipped
     * @param e - AssumptionViolatedException
     * @param description - Test description
     */
    protected void skipped(AssumptionViolatedException e, Description description);

    /**
     * Called when test is about to start
     * @param description - Test description
     */
    protected void starting(Description description);

    /**
     * Called when test finishes (success or failure)
     * @param description - Test description
     */
    protected void finished(Description description);
}

Usage Examples:

import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
import org.junit.Rule;
import org.junit.Test;

public class DetailedWatcher extends TestWatcher {
    @Override
    protected void starting(Description description) {
        System.out.println("Starting: " + description.getMethodName());
    }

    @Override
    protected void succeeded(Description description) {
        System.out.println("PASSED: " + description.getMethodName());
    }

    @Override
    protected void failed(Throwable e, Description description) {
        System.out.println("FAILED: " + description.getMethodName());
        System.out.println("Error: " + e.getMessage());
    }

    @Override
    protected void finished(Description description) {
        System.out.println("Finished: " + description.getMethodName());
    }
}

public class WatchedTest {
    @Rule
    public TestWatcher watcher = new DetailedWatcher();

    @Test
    public void testSomething() {
        assertTrue(true);
    }
}

// Screenshot on failure example
public class ScreenshotOnFailure extends TestWatcher {
    @Override
    protected void failed(Throwable e, Description description) {
        String testName = description.getMethodName();
        takeScreenshot(testName + "_failure.png");
    }

    private void takeScreenshot(String filename) {
        // Screenshot logic
    }
}

Stopwatch

Measures and logs test execution time. Provides hooks for accessing timing information.

/**
 * Rule for measuring test execution time
 */
public class Stopwatch implements TestRule {
    /**
     * Get runtime in milliseconds
     * @param unit - Time unit to convert to
     * @return Runtime in specified unit
     */
    public long runtime(TimeUnit unit);

    /**
     * Called when test succeeds
     * @param nanos - Execution time in nanoseconds
     * @param description - Test description
     */
    protected void succeeded(long nanos, Description description);

    /**
     * Called when test fails
     * @param nanos - Execution time in nanoseconds
     * @param e - Throwable that caused failure
     * @param description - Test description
     */
    protected void failed(long nanos, Throwable e, Description description);

    /**
     * Called when test is skipped
     * @param nanos - Time until skip
     * @param e - AssumptionViolatedException
     * @param description - Test description
     */
    protected void skipped(long nanos, AssumptionViolatedException e, Description description);

    /**
     * Called when test finishes
     * @param nanos - Execution time in nanoseconds
     * @param description - Test description
     */
    protected void finished(long nanos, Description description);
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.Stopwatch;
import org.junit.runner.Description;
import java.util.concurrent.TimeUnit;

public class TimingTest {
    @Rule
    public Stopwatch stopwatch = new Stopwatch() {
        @Override
        protected void succeeded(long nanos, Description description) {
            long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
            System.out.println(description.getMethodName() + " succeeded in " + millis + "ms");
        }

        @Override
        protected void failed(long nanos, Throwable e, Description description) {
            long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
            System.out.println(description.getMethodName() + " failed in " + millis + "ms");
        }

        @Override
        protected void finished(long nanos, Description description) {
            long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
            System.out.println(description.getMethodName() + " finished in " + millis + "ms");
        }
    };

    @Test
    public void performanceTest() {
        // Timing is automatically recorded
        performOperation();
    }
}

// Logging slow tests
public class SlowTestLogger extends Stopwatch {
    private static final long THRESHOLD_MS = 1000;

    @Override
    protected void finished(long nanos, Description description) {
        long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
        if (millis > THRESHOLD_MS) {
            System.out.println("SLOW TEST: " + description.getMethodName()
                + " took " + millis + "ms");
        }
    }
}

Verifier

Base class for rules that verify state after test execution. Similar to custom assertions.

/**
 * Base class for rules that verify conditions after test
 */
public abstract class Verifier implements TestRule {
    /**
     * Override to verify conditions after test
     * Throw exception if verification fails
     */
    protected void verify() throws Throwable;
}

Usage Examples:

import org.junit.rules.Verifier;
import org.junit.Rule;
import org.junit.Test;

public class LogVerifier extends Verifier {
    private Logger logger;

    public LogVerifier(Logger logger) {
        this.logger = logger;
    }

    @Override
    protected void verify() {
        if (logger.hasErrors()) {
            throw new AssertionError("Test produced error logs: " + logger.getErrors());
        }
    }
}

public class VerifiedTest {
    private Logger logger = new Logger();

    @Rule
    public Verifier logVerifier = new LogVerifier(logger);

    @Test
    public void testSomething() {
        // Test code
        // After test, verifier checks that no errors were logged
    }
}

// State verification example
public class StateVerifier extends Verifier {
    private SystemState state;

    public StateVerifier(SystemState state) {
        this.state = state;
    }

    @Override
    protected void verify() {
        if (!state.isClean()) {
            throw new AssertionError("System left in dirty state");
        }
    }
}

DisableOnDebug

Wraps another rule and disables it when running in debug mode. Useful for timeout rules that interfere with debugging.

/**
 * Disables a rule when running in debug mode
 */
public class DisableOnDebug implements TestRule {
    /**
     * Create a rule that is disabled during debugging
     * @param rule - Rule to wrap
     */
    public DisableOnDebug(TestRule rule);

    /**
     * Check if currently debugging
     * @return true if debug mode detected
     */
    public boolean isDebugging();
}

Usage Examples:

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.DisableOnDebug;
import org.junit.rules.Timeout;

public class DebuggableTest {
    @Rule
    public TestRule timeout = new DisableOnDebug(Timeout.seconds(10));

    @Test
    public void testWithTimeout() {
        // Timeout applies normally, but is disabled when debugging
        // so you can use breakpoints without timeout failures
        performOperation();
    }
}

Types

/**
 * Represents a statement in test execution
 */
public abstract class Statement {
    /**
     * Execute the statement
     */
    public abstract void evaluate() throws Throwable;
}

/**
 * Legacy rule interface (prefer TestRule)
 */
@Deprecated
public interface MethodRule {
    Statement apply(Statement base, FrameworkMethod method, Object target);
}

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