or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

actor-refs.mdconfiguration.mdcore-testing.mddispatchers.mdevent-filtering.mdindex.mdjava-dsl.mdpackage-functions.mdsynchronization.mdtest-actors.mdutilities.md
tile.json

java-dsl.mddocs/

Java DSL

Complete Java API providing equivalent functionality to the Scala API with Java-friendly method signatures and type usage.

Capabilities

javadsl.TestKit Class

Java API for TestKit functionality with Java-friendly types and method signatures.

package akka.testkit.javadsl

class TestKit(system: ActorSystem) {
  // Message expectation methods
  def expectMsg(msg: Object): Object
  def expectMsg(max: java.time.Duration, msg: Object): Object
  def expectMsgClass[T](c: Class[T]): T
  def expectMsgClass[T](max: java.time.Duration, c: Class[T]): T
  def expectMsgAnyOf(objects: Object*): Object
  def expectMsgAnyOf(max: java.time.Duration, objects: Object*): Object
  def expectMsgAllOf(objects: Object*): java.util.List[Object]
  def expectMsgAllOf(max: java.time.Duration, objects: Object*): java.util.List[Object]
  def expectNoMessage(): Unit
  def expectNoMessage(max: java.time.Duration): Unit
  
  // Message reception methods
  def receiveN(n: Int): java.util.List[Object]
  def receiveN(n: Int, max: java.time.Duration): java.util.List[Object]
  def receiveOne(max: java.time.Duration): Object
  
  // Timing and condition methods
  def within[T](max: java.time.Duration, f: Supplier[T]): T
  def within[T](min: java.time.Duration, max: java.time.Duration, f: Supplier[T]): T
  def awaitCond(p: Supplier[java.lang.Boolean]): Unit
  def awaitCond(p: Supplier[java.lang.Boolean], max: java.time.Duration): Unit
  def awaitCond(p: Supplier[java.lang.Boolean], max: java.time.Duration, interval: java.time.Duration): Unit
  def awaitAssert[A](a: Supplier[A]): A
  def awaitAssert[A](a: Supplier[A], max: java.time.Duration): A
  def awaitAssert[A](a: Supplier[A], max: java.time.Duration, interval: java.time.Duration): A
  
  // Actor management methods
  def watch(ref: ActorRef): ActorRef
  def unwatch(ref: ActorRef): ActorRef
  def childActorOf(props: Props): ActorRef
  def childActorOf(props: Props, name: String): ActorRef
  
  // Properties
  def getTestActor(): ActorRef
  def getSystem(): ActorSystem
  def duration(s: String): java.time.Duration
  def dilated(d: java.time.Duration): java.time.Duration
}

Usage Example:

import akka.actor.*;
import akka.testkit.javadsl.TestKit;
import org.junit.Test;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import java.time.Duration;

public class JavaTestKitExample {
    static ActorSystem system;

    @BeforeClass
    public static void setup() {
        system = ActorSystem.create("TestSystem");
    }

    @AfterClass  
    public static void teardown() {
        TestKit.shutdownActorSystem(system);
        system = null;
    }

    // Simple echo actor for testing
    static class EchoActor extends AbstractActor {
        @Override
        public Receive createReceive() {
            return receiveBuilder()
                .matchAny(msg -> getSender().tell(msg, getSelf()))
                .build();
        }
    }

    @Test
    public void testEchoActor() {
        new TestKit(system) {{
            final ActorRef echoActor = system.actorOf(Props.create(EchoActor.class));
            
            // Basic message expectation
            echoActor.tell("hello", getTestActor());
            expectMsg("hello");
            
            // Expectation with timeout
            echoActor.tell(42, getTestActor());
            expectMsg(Duration.ofSeconds(3), 42);
            
            // Expect specific type
            echoActor.tell("test", getTestActor());
            expectMsgClass(String.class);
            
            // Multiple messages
            echoActor.tell("first", getTestActor());
            echoActor.tell("second", getTestActor());
            expectMsgAllOf("first", "second");
        }};
    }

    @Test
    public void testTimingAndConditions() {
        new TestKit(system) {{
            final boolean[] condition = {false};
            
            // Schedule condition to become true
            system.scheduler().scheduleOnce(
                Duration.ofMillis(500),
                () -> condition[0] = true,
                system.dispatcher()
            );
            
            // Wait for condition
            awaitCond(() -> condition[0], Duration.ofSeconds(2));
            
            // Time-bounded execution
            within(Duration.ofSeconds(1), () -> {
                expectNoMessage(Duration.ofMillis(100));
                return null;
            });
        }};
    }
}

javadsl.EventFilter Class

Java API for event filtering with builder-style methods.

package akka.testkit.javadsl

class EventFilter {
  // Execution methods
  def intercept[T](code: Supplier[T]): T
  def intercept(code: Runnable): Unit
  
  // Configuration methods (return new EventFilter for chaining)
  def message(msg: String): EventFilter
  def startsWith(msg: String): EventFilter
  def matches(regex: String): EventFilter
  def from(source: String): EventFilter
  def occurrences(number: Int): EventFilter
  
  // Static factory methods
  static EventFilter error(): EventFilter
  static EventFilter error(Class[_ <: Throwable] clazz): EventFilter
  static EventFilter warning(): EventFilter
  static EventFilter info(): EventFilter
  static EventFilter debug(): EventFilter
  static EventFilter custom(Function[LogEvent, java.lang.Boolean] test): EventFilter
}

Usage Example:

import akka.testkit.javadsl.EventFilter;
import akka.event.Logging;

public class JavaEventFilterExample {
    @Test
    public void testEventFiltering() {
        new TestKit(system) {{
            // Simple error filtering
            EventFilter.error()
                .message("Expected error")
                .occurrences(1)
                .intercept(() -> {
                    ActorRef actor = system.actorOf(Props.create(ThrowingActor.class));
                    actor.tell("throw", getTestActor());
                });
            
            // Warning filtering with pattern
            EventFilter.warning()
                .matches("User \\d+ logged in")
                .intercept(() -> {
                    // Code that logs user login messages
                });
            
            // Custom filtering
            EventFilter.custom(event -> 
                event instanceof Logging.Error && 
                event.message().toString().contains("database")
            ).intercept(() -> {
                // Code that generates database errors  
            });
            
            // Multiple filters (using separate calls)
            EventFilter.error().occurrences(1).intercept(() -> {
                EventFilter.warning().startsWith("Deprecated").intercept(() -> {
                    // Code that generates both errors and warnings
                });
            });
        }};
    }
}

Java Functional Interfaces Integration

TestKit integrates well with Java 8+ functional interfaces:

import java.util.function.*;
import java.util.concurrent.CompletableFuture;

public class JavaFunctionalExample {
    @Test
    public void testWithLambdas() {
        new TestKit(system) {{
            // Using lambdas with awaitCond
            CompletableFuture<String> future = CompletableFuture
                .supplyAsync(() -> "result")
                .thenApplyAsync(s -> s.toUpperCase());
            
            awaitCond(() -> future.isDone(), Duration.ofSeconds(2));
            
            // Using method references
            Consumer<String> sendToActor = msg -> 
                getTestActor().tell(msg, ActorRef.noSender());
            
            within(Duration.ofSeconds(1), () -> {
                sendToActor.accept("test message");
                expectMsg("test message");
                return null;
            });
            
            // Functional event filtering
            EventFilter.custom(event -> 
                event.logLevel().equals(Logging.InfoLevel()) &&
                event.toString().contains("important")
            ).intercept(() -> {
                // Code that generates important info messages
            });
        }};
    }
}

Java Collections Integration

TestKit methods return Java collections where appropriate:

import java.util.*;

public class JavaCollectionsExample {
    @Test
    public void testCollections() {
        new TestKit(system) {{
            ActorRef actor = system.actorOf(Props.create(EchoActor.class));
            
            // Send multiple messages
            List<String> messages = Arrays.asList("msg1", "msg2", "msg3");
            messages.forEach(msg -> actor.tell(msg, getTestActor()));
            
            // Receive as Java List
            List<Object> received = receiveN(3, Duration.ofSeconds(2));
            
            // Convert and verify
            List<String> receivedStrings = received.stream()
                .map(Object::toString)
                .collect(java.util.stream.Collectors.toList());
                
            assertEquals(messages, receivedStrings);
            
            // Expect multiple messages (returns Java List)
            actor.tell("a", getTestActor());
            actor.tell("b", getTestActor());
            List<Object> results = expectMsgAllOf(Duration.ofSeconds(1), "a", "b");
            
            assertEquals(2, results.size());
            assertTrue(results.contains("a"));
            assertTrue(results.contains("b"));
        }};
    }
}

Exception Handling in Java DSL

public class JavaExceptionHandlingExample {
    @Test
    public void testExceptionHandling() {
        new TestKit(system) {{
            // Handle timeout exceptions
            try {
                expectMsg(Duration.ofMillis(100), "never-sent");
                fail("Should have timed out");
            } catch (AssertionError e) {
                // Expected timeout
                assertTrue(e.getMessage().contains("timeout"));
            }
            
            // Test actor failures with event filtering
            EventFilter.error(RuntimeException.class)
                .message("Test exception")
                .intercept(() -> {
                    ActorRef actor = system.actorOf(Props.create(FailingActor.class));
                    actor.tell("fail", getTestActor());
                });
        }};
    }
    
    static class FailingActor extends AbstractActor {
        @Override
        public Receive createReceive() {
            return receiveBuilder()
                .matchEquals("fail", msg -> {
                    throw new RuntimeException("Test exception");
                })
                .build();
        }
    }
}

Integration with JUnit and TestNG

JUnit Integration:

import org.junit.*;
import org.junit.rules.TestName;

public class JUnitIntegrationExample {
    private static ActorSystem system;
    private TestKit testKit;
    
    @Rule
    public TestName testName = new TestName();
    
    @BeforeClass
    public static void setupClass() {
        system = ActorSystem.create("TestSystem");
    }
    
    @Before
    public void setup() {
        testKit = new TestKit(system);
    }
    
    @After
    public void cleanup() {
        // Individual test cleanup if needed
    }
    
    @AfterClass
    public static void teardownClass() {
        TestKit.shutdownActorSystem(system);
    }
    
    @Test
    public void testActorBehavior() {
        // Use testKit for testing
        ActorRef actor = system.actorOf(Props.create(MyActor.class), 
            "actor-" + testName.getMethodName());
        
        actor.tell("test", testKit.getTestActor());
        testKit.expectMsg("response");
    }
}

TestNG Integration:

import org.testng.annotations.*;

public class TestNGIntegrationExample {
    private ActorSystem system;
    private TestKit testKit;
    
    @BeforeClass
    public void setupClass() {
        system = ActorSystem.create("TestSystem");
    }
    
    @BeforeMethod
    public void setup() {
        testKit = new TestKit(system);
    }
    
    @AfterClass
    public void teardownClass() {
        TestKit.shutdownActorSystem(system);
    }
    
    @Test
    public void testExample() {
        // TestNG test using TestKit
        testKit.within(Duration.ofSeconds(2), () -> {
            // Test code
            return null;
        });
    }
}

Best Practices for Java DSL

  1. Use Java 8+ Features: Leverage lambdas, streams, and method references
  2. Handle Timeouts: Always specify reasonable timeouts for expectations
  3. Resource Management: Use try-with-resources or proper cleanup
  4. Type Safety: Use generic methods where available for type safety
  5. Integration: Combine with testing frameworks like JUnit/TestNG
// Good: Use lambdas and proper timeouts
testKit.awaitCond(() -> actor.isTerminated(), Duration.ofSeconds(3));

// Good: Type-safe message expectations
String response = testKit.expectMsgClass(Duration.ofSeconds(1), String.class);

// Good: Functional event filtering
EventFilter.custom(event -> event.logLevel().equals(Logging.ErrorLevel()))
    .intercept(() -> triggerError());

// Good: Resource cleanup
@After
public void cleanup() {
    if (testKit != null) {
        // Clean up test resources
    }
}