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

utilities.mddocs/

Helper Utilities

Additional utility functions and classes for common testing scenarios, including socket utilities, test exceptions, and serialization helpers.

Capabilities

SocketUtil Object

Utilities for getting free socket addresses in tests.

object SocketUtil {
  // Port utilities
  def temporaryLocalPort(udp: Boolean = false): Int
  def temporaryLocalAddress(udp: Boolean = false): InetSocketAddress
  
  // Server address utilities
  def temporaryServerAddress(address: String = "127.0.0.1", udp: Boolean = false): InetSocketAddress
  def temporaryServerAddresses(
    numberOfAddresses: Int, 
    hostname: String = "127.0.0.1", 
    udp: Boolean = false
  ): Seq[InetSocketAddress]
  
  // Unbound address utility
  def notBoundServerAddress(address: String = "127.0.0.1", udp: Boolean = false): InetSocketAddress
}

Usage Examples:

import akka.testkit.SocketUtil

class NetworkingTest extends TestKit(ActorSystem("TestSystem")) {
  "SocketUtil" should {
    "provide free TCP ports" in {
      val port1 = SocketUtil.temporaryLocalPort()
      val port2 = SocketUtil.temporaryLocalPort()
      
      port1 should not equal port2
      port1 should be > 1024
      port2 should be > 1024
      
      // Use ports for testing
      val server = startTestServer(port1)
      val client = connectToServer("localhost", port1)
      
      // Test networking code
      client.send("hello")
      server.expectReceive("hello")
    }
    
    "provide free UDP ports" in {
      val udpPort = SocketUtil.temporaryLocalPort(udp = true)
      val udpAddress = SocketUtil.temporaryLocalAddress(udp = true)
      
      udpAddress.getPort should equal(udpPort)
      
      // Use for UDP testing
      val udpSocket = new DatagramSocket(udpPort)
      // Test UDP functionality
    }
    
    "provide server addresses" in {
      val address = SocketUtil.temporaryServerAddress("0.0.0.0")
      address.getHostString should be("0.0.0.0")
      address.getPort should be > 1024
      
      // Multiple addresses for cluster testing
      val addresses = SocketUtil.temporaryServerAddresses(3, "127.0.0.1")
      addresses should have size 3
      addresses.map(_.getPort).distinct should have size 3
    }
  }
}

TestException Case Class

Predefined exception for tests without stack trace.

final case class TestException(message: String) extends RuntimeException(message) with NoStackTrace

Usage Examples:

import akka.testkit.TestException

class ExceptionTest extends TestKit(ActorSystem("TestSystem")) {
  "TestException" should {
    "be lightweight for testing" in {
      val exception = TestException("Test error message")
      
      exception.getMessage should be("Test error message")
      exception.getStackTrace should be(empty) // No stack trace for performance
      
      // Use in actor testing
      EventFilter[TestException](message = "Test error message").intercept {
        val actor = system.actorOf(Props(new Actor {
          def receive = {
            case "throw" => throw TestException("Test error message")
          }
        }))
        actor ! "throw"
      }
    }
    
    "be useful for expected failures" in {
      class FailingActor extends Actor {
        def receive = {
          case "fail" => throw TestException("Expected failure")
          case msg => sender() ! msg
        }
      }
      
      val actor = system.actorOf(Props[FailingActor]())
      
      // Test normal operation
      actor ! "hello"
      expectMsg("hello")
      
      // Test expected failure
      EventFilter[TestException](message = "Expected failure").intercept {
        actor ! "fail"
      }
    }
  }
}

Java Serialization Utilities

Utilities for Java serialization in tests.

// Marker trait for test messages using Java serialization
trait JavaSerializable

// Java serializer for ad-hoc test messages
class TestJavaSerializer extends Serializer {
  def identifier: Int
  def includeManifest: Boolean
  def toBinary(o: AnyRef): Array[Byte]
  def fromBinary(bytes: Array[Byte], manifest: Option[Class[_]]): AnyRef
}

Usage Examples:

import akka.testkit.JavaSerializable

// Test message with Java serialization
case class TestMessage(data: String, id: Int) extends JavaSerializable

class SerializationTest extends TestKit(ActorSystem("TestSystem")) {
  "Java serialization" should {
    "work with test messages" in {
      val message = TestMessage("test data", 123)
      
      val actor = system.actorOf(Props(new Actor {
        def receive = {
          case msg: TestMessage => sender() ! msg.copy(data = msg.data.toUpperCase)
        }
      }))
      
      actor ! message
      expectMsg(TestMessage("TEST DATA", 123))
    }
  }
}

TestKitUtils Object

Utility methods for TestKit operations.

object TestKitUtils {
  // Extract test name from call stack
  def testNameFromCallStack(classToStartFrom: Class[_], fallback: String): String
}

Usage Example:

import akka.testkit.TestKitUtils

class UtilsTest extends TestKit(ActorSystem("TestSystem")) {
  "TestKitUtils" should {
    "extract test names" in {
      val testName = TestKitUtils.testNameFromCallStack(classOf[UtilsTest], "default-test")
      testName should include("extract test names")
      
      // Useful for dynamic actor naming
      val actor = system.actorOf(Props[EchoActor](), s"echo-$testName")
      actor.path.name should startWith("echo-")
    }
  }
}

Configuration Utilities

Helper functions for test configuration management.

// Access test configuration
def testKitSettings(implicit system: ActorSystem): TestKitSettings = TestKitExtension(system)

// Time dilation helpers (from package object)
implicit class TestDuration(duration: FiniteDuration) {
  def dilated(implicit system: ActorSystem): FiniteDuration
}

Usage Examples:

import akka.testkit._
import scala.concurrent.duration._

class ConfigurationTest extends TestKit(ActorSystem("TestSystem")) {
  "Configuration utilities" should {
    "provide test settings" in {
      val settings = testKitSettings
      
      settings.TestTimeFactor should be >= 1.0
      settings.SingleExpectDefaultTimeout should be > Duration.Zero
      settings.DefaultTimeout.duration should be > Duration.Zero
    }
    
    "dilate time for tests" in {
      val originalDuration = 1.second
      val dilated = originalDuration.dilated
      
      // Dilated duration accounts for slow test environments
      dilated should be >= originalDuration
      
      // Use dilated timeouts in tests
      within(5.seconds.dilated) {
        // Test code that might run slowly in CI environments
        Thread.sleep(100)
        expectNoMessage(100.millis.dilated)
      }
    }
  }
}

Custom Test Utilities

You can create custom utilities for your specific testing needs:

// Custom test utilities object
object MyTestUtils {
  // Helper for creating actors with test-specific configuration
  def testActorOf[T <: Actor](props: Props, name: String)(implicit system: ActorSystem): ActorRef = {
    system.actorOf(props.withDispatcher("akka.test.calling-thread-dispatcher"), name)
  }
  
  // Helper for temporary files in tests
  def withTempFile[T](content: String)(test: File => T): T = {
    val file = File.createTempFile("test", ".tmp")
    try {
      Files.write(file.toPath, content.getBytes)
      test(file)
    } finally {
      file.delete()
    }
  }
  
  // Helper for timing operations
  def timed[T](operation: => T): (T, FiniteDuration) = {
    val start = System.nanoTime()
    val result = operation
    val duration = (System.nanoTime() - start).nanos
    (result, duration)
  }
}

// Usage in tests
class CustomUtilsTest extends TestKit(ActorSystem("TestSystem")) {
  import MyTestUtils._
  
  "Custom utilities" should {
    "help with actor creation" in {
      val actor = testActorOf(Props[EchoActor](), "test-echo")
      actor ! "hello"
      expectMsg("hello")
    }
    
    "provide temp file support" in {
      withTempFile("test content") { file =>
        file.exists() should be(true)
        Source.fromFile(file).mkString should be("test content")
      }
    }
    
    "measure timing" in {
      val (result, duration) = timed {
        Thread.sleep(100)
        "completed"
      }
      
      result should be("completed")
      duration should be >= 100.millis
    }
  }
}

Best Practices

  1. Use SocketUtil for Network Testing: Always use free ports to avoid conflicts
  2. TestException for Expected Failures: Use TestException for lightweight exception testing
  3. Time Dilation: Use dilated timeouts for reliable CI testing
  4. Resource Cleanup: Clean up sockets, files, and other resources after tests
  5. Descriptive Names: Use meaningful names when creating temporary resources
// Good: Use utilities for reliable testing
val port = SocketUtil.temporaryLocalPort()
val server = startServer(port)
try {
  // Test code
} finally {
  server.stop()
}

// Good: Use time dilation for robustness
within(5.seconds.dilated) {
  heavyOperation()
  expectMsg("completed")
}

// Good: Use TestException for expected failures
EventFilter[TestException](message = "Expected test failure").intercept {
  actor ! TriggerFailure()
}