or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

actor-references.mdcore-testing.mddeterministic-execution.mdevent-filtering.mdindex.mdjava-api.mdtest-utilities.mdutilities-config.md

java-api.mddocs/

0

# Java API

1

2

Akka TestKit provides a comprehensive Java API that offers the same functionality as the Scala API with Java-friendly method signatures, types, and modern Java 8+ features. The Java API is located in the `akka.testkit.javadsl` package and includes specialized classes designed for Java developers.

3

4

## Modern Java API (javadsl)

5

6

### javadsl.TestKit { .api }

7

8

```scala

9

class TestKit(system: ActorSystem) {

10

// Java Duration-based methods

11

def expectMsg(duration: java.time.Duration, obj: AnyRef): AnyRef

12

def expectMsgClass(duration: java.time.Duration, clazz: Class[_]): AnyRef

13

def expectMsgEquals(duration: java.time.Duration, obj: AnyRef): AnyRef

14

def expectNoMessage(duration: java.time.Duration): Unit

15

def expectNoMessage(): Unit

16

17

// Supplier-based methods for lazy evaluation

18

def within(duration: java.time.Duration, supplier: Supplier[_]): AnyRef

19

def awaitCond(duration: java.time.Duration, supplier: Supplier[Boolean]): Unit

20

def awaitAssert(duration: java.time.Duration, supplier: Supplier[_]): AnyRef

21

22

// Message reception

23

def receiveOne(duration: java.time.Duration): AnyRef

24

def receiveN(n: Int, duration: java.time.Duration): java.util.List[AnyRef]

25

26

// Actor references and system access

27

def getSystem(): ActorSystem

28

def getTestActor(): ActorRef

29

def getLastSender(): ActorRef

30

31

// Lifecycle

32

def watch(actorRef: ActorRef): ActorRef

33

def unwatch(actorRef: ActorRef): ActorRef

34

}

35

```

36

37

Modern Java API with `java.time.Duration` support and Java 8+ functional interfaces.

38

39

### javadsl.EventFilter { .api }

40

41

```scala

42

class EventFilter(clazz: Class[_], system: ActorSystem) {

43

def message(pattern: String): EventFilter

44

def source(source: String): EventFilter

45

def occurrences(count: Int): EventFilter

46

def from(source: String): EventFilter

47

def intercept[T](supplier: Supplier[T]): T

48

def matches(logEvent: LogEvent): Boolean

49

}

50

51

object EventFilter {

52

def error(system: ActorSystem): EventFilter

53

def warning(system: ActorSystem): EventFilter

54

def info(system: ActorSystem): EventFilter

55

def debug(system: ActorSystem): EventFilter

56

def forException(clazz: Class[_ <: Throwable], system: ActorSystem): EventFilter

57

}

58

```

59

60

Fluent Java API for event filtering with method chaining.

61

62

## Usage Examples

63

64

### Basic TestKit Usage

65

66

```java

67

import akka.actor.ActorRef;

68

import akka.actor.ActorSystem;

69

import akka.actor.Props;

70

import akka.testkit.javadsl.TestKit;

71

import java.time.Duration;

72

import org.junit.Test;

73

import org.junit.AfterClass;

74

75

public class MyActorTest {

76

static ActorSystem system = ActorSystem.create("TestSystem");

77

78

@Test

79

public void testActorResponse() {

80

new TestKit(system) {{

81

ActorRef actor = system.actorOf(Props.create(MyActor.class));

82

83

// Send message and expect response

84

actor.tell("ping", getTestActor());

85

expectMsg(Duration.ofSeconds(1), "pong");

86

}};

87

}

88

89

@Test

90

public void testNoMessage() {

91

new TestKit(system) {{

92

ActorRef actor = system.actorOf(Props.create(QuietActor.class));

93

94

actor.tell("ignore-me", getTestActor());

95

expectNoMessage(Duration.ofMillis(500));

96

}};

97

}

98

99

@AfterClass

100

public static void teardown() {

101

TestKit.shutdownActorSystem(system);

102

}

103

}

104

```

105

106

### Message Expectations with Types

107

108

```java

109

import akka.testkit.javadsl.TestKit;

110

111

public class TypedMessageTest {

112

@Test

113

public void testTypedMessages() {

114

new TestKit(system) {{

115

ActorRef actor = system.actorOf(Props.create(StatusActor.class));

116

117

// Expect specific message class

118

actor.tell("get-status", getTestActor());

119

StatusResponse response = expectMsgClass(

120

Duration.ofSeconds(1),

121

StatusResponse.class

122

);

123

124

assertEquals("active", response.getStatus());

125

assertEquals(42, response.getCount());

126

}};

127

}

128

}

129

```

130

131

### Timing Control with Suppliers

132

133

```java

134

import java.util.function.Supplier;

135

136

public class TimingTest {

137

@Test

138

public void testWithinBlock() {

139

new TestKit(system) {{

140

ActorRef actor = system.actorOf(Props.create(TimedActor.class));

141

142

// Execute within time bounds using Supplier

143

String result = (String) within(Duration.ofSeconds(3), () -> {

144

actor.tell("timed-request", getTestActor());

145

return expectMsg(Duration.ofSeconds(2), "timed-response");

146

});

147

148

assertEquals("timed-response", result);

149

}};

150

}

151

152

@Test

153

public void testAwaitCondition() {

154

new TestKit(system) {{

155

SharedState state = new SharedState();

156

ActorRef actor = system.actorOf(Props.create(StateActor.class, state));

157

158

actor.tell("initialize", getTestActor());

159

160

// Wait for condition with Supplier

161

awaitCond(Duration.ofSeconds(5), () -> state.isReady());

162

163

assertTrue(state.isReady());

164

}};

165

}

166

}

167

```

168

169

### Message Reception

170

171

```java

172

public class MessageReceptionTest {

173

@Test

174

public void testReceiveMessages() {

175

new TestKit(system) {{

176

ActorRef actor = system.actorOf(Props.create(BatchActor.class));

177

178

// Trigger batch of messages

179

actor.tell("send-batch", getTestActor());

180

181

// Receive single message

182

Object first = receiveOne(Duration.ofSeconds(1));

183

assertEquals("message-1", first);

184

185

// Receive multiple messages

186

List<Object> messages = receiveN(3, Duration.ofSeconds(2));

187

assertEquals(3, messages.size());

188

assertEquals("message-2", messages.get(0));

189

assertEquals("message-3", messages.get(1));

190

assertEquals("message-4", messages.get(2));

191

}};

192

}

193

}

194

```

195

196

### Actor Lifecycle Testing

197

198

```java

199

public class LifecycleTest {

200

@Test

201

public void testActorTermination() {

202

new TestKit(system) {{

203

ActorRef actor = system.actorOf(Props.create(LifecycleActor.class));

204

205

// Watch for termination

206

watch(actor);

207

208

// Trigger termination

209

actor.tell(PoisonPill.getInstance(), ActorRef.noSender());

210

211

// Expect termination message

212

Terminated terminated = expectMsgClass(

213

Duration.ofSeconds(1),

214

Terminated.class

215

);

216

217

assertEquals(actor, terminated.getActor());

218

}};

219

}

220

}

221

```

222

223

## Event Filtering with Java API

224

225

### Basic Event Filtering

226

227

```java

228

import akka.testkit.javadsl.EventFilter;

229

230

public class EventFilterTest {

231

@Test

232

public void testErrorFiltering() {

233

new TestKit(system) {{

234

ActorRef actor = system.actorOf(Props.create(LoggingActor.class));

235

236

// Filter expected error messages

237

EventFilter.error(system)

238

.message("Something went wrong")

239

.occurrences(1)

240

.intercept(() -> {

241

actor.tell("cause-error", getTestActor());

242

return expectMsg(Duration.ofSeconds(1), "error-handled");

243

});

244

}};

245

}

246

247

@Test

248

public void testExceptionFiltering() {

249

new TestKit(system) {{

250

ActorRef actor = system.actorOf(Props.create(FaultyActor.class));

251

252

// Filter specific exception type

253

EventFilter.forException(RuntimeException.class, system)

254

.occurrences(1)

255

.intercept(() -> {

256

actor.tell("throw-exception", getTestActor());

257

return null;

258

});

259

}};

260

}

261

}

262

```

263

264

### Advanced Event Filtering

265

266

```java

267

public class AdvancedEventFilterTest {

268

@Test

269

public void testChainedFiltering() {

270

new TestKit(system) {{

271

ActorRef actor = system.actorOf(Props.create(VerboseActor.class));

272

273

// Chain multiple filter conditions

274

EventFilter.info(system)

275

.source("akka://TestSystem/user/verbose-actor")

276

.message("Processing started")

277

.occurrences(1)

278

.intercept(() -> {

279

actor.tell("start-processing", getTestActor());

280

return expectMsg(Duration.ofSeconds(1), "processing-started");

281

});

282

}};

283

}

284

285

@Test

286

public void testMultipleFilters() {

287

new TestKit(system) {{

288

ActorRef actor = system.actorOf(Props.create(MultiLogActor.class));

289

290

// Multiple filters for different log levels

291

EventFilter.warning(system).occurrences(1).intercept(() -> {

292

return EventFilter.error(system).occurrences(1).intercept(() -> {

293

actor.tell("log-multiple", getTestActor());

294

return expectMsg(Duration.ofSeconds(1), "logged");

295

});

296

});

297

}};

298

}

299

}

300

```

301

302

## TestProbe Java Usage

303

304

```java

305

import akka.testkit.TestProbe;

306

307

public class TestProbeExample {

308

@Test

309

public void testWithProbe() {

310

new TestKit(system) {{

311

// Create test probe

312

TestProbe probe = TestProbe.create(system);

313

ActorRef actor = system.actorOf(Props.create(InteractionActor.class));

314

315

// Register probe as listener

316

actor.tell(new RegisterListener(probe.ref()), getTestActor());

317

expectMsg(Duration.ofSeconds(1), "listener-registered");

318

319

// Trigger notification

320

actor.tell("notify-listeners", getTestActor());

321

322

// Probe receives notification

323

probe.expectMsg(Duration.ofSeconds(1), "notification");

324

325

// Probe can reply

326

probe.reply("acknowledged");

327

328

expectMsg(Duration.ofSeconds(1), "ack-received");

329

}};

330

}

331

}

332

```

333

334

## Legacy Java API (Deprecated)

335

336

### JavaTestKit (Deprecated) { .api }

337

338

```java

339

public class JavaTestKit {

340

public JavaTestKit(ActorSystem system) { }

341

342

// Legacy methods using Scala Duration

343

public Object expectMsg(scala.concurrent.duration.Duration duration, Object obj)

344

public Object expectMsgClass(scala.concurrent.duration.Duration duration, Class<?> clazz)

345

public void expectNoMsg(scala.concurrent.duration.Duration duration)

346

347

// Static utility methods

348

public static void shutdownActorSystem(ActorSystem system)

349

public static void shutdownActorSystem(ActorSystem system, scala.concurrent.duration.Duration duration)

350

public static void shutdownActorSystem(ActorSystem system, scala.concurrent.duration.Duration duration, boolean verifySystemShutdown)

351

}

352

```

353

354

**Note**: JavaTestKit is deprecated in favor of the modern `javadsl.TestKit`.

355

356

### Migration from Legacy API

357

358

```java

359

// Old way (deprecated)

360

import akka.testkit.JavaTestKit;

361

import scala.concurrent.duration.Duration;

362

363

public class OldStyleTest extends JavaTestKit {

364

public OldStyleTest() {

365

super(system);

366

}

367

368

@Test

369

public void oldTest() {

370

ActorRef actor = system.actorOf(Props.create(MyActor.class));

371

actor.tell("message", getRef());

372

expectMsg(Duration.create(1, "second"), "response");

373

}

374

}

375

376

// New way (recommended)

377

import akka.testkit.javadsl.TestKit;

378

import java.time.Duration;

379

380

public class NewStyleTest {

381

@Test

382

public void newTest() {

383

new TestKit(system) {{

384

ActorRef actor = system.actorOf(Props.create(MyActor.class));

385

actor.tell("message", getTestActor());

386

expectMsg(Duration.ofSeconds(1), "response");

387

}};

388

}

389

}

390

```

391

392

## Java 8+ Features Integration

393

394

### CompletableFuture Integration

395

396

```java

397

import java.util.concurrent.CompletableFuture;

398

399

public class AsyncTest {

400

@Test

401

public void testAsyncOperations() {

402

new TestKit(system) {{

403

ActorRef actor = system.actorOf(Props.create(AsyncActor.class));

404

405

// Use CompletableFuture with TestKit

406

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {

407

actor.tell("async-request", getTestActor());

408

return (String) expectMsg(Duration.ofSeconds(5), "async-response");

409

});

410

411

String result = future.join();

412

assertEquals("async-response", result);

413

}};

414

}

415

}

416

```

417

418

### Stream Integration

419

420

```java

421

import java.util.stream.IntStream;

422

423

public class StreamTest {

424

@Test

425

public void testWithStreams() {

426

new TestKit(system) {{

427

ActorRef actor = system.actorOf(Props.create(CounterActor.class));

428

429

// Send multiple messages using streams

430

IntStream.range(1, 6)

431

.forEach(i -> actor.tell("increment", getTestActor()));

432

433

// Expect multiple responses

434

IntStream.range(1, 6)

435

.forEach(expected -> {

436

Integer count = (Integer) expectMsgClass(Duration.ofSeconds(1), Integer.class);

437

assertEquals(expected, count.intValue());

438

});

439

}};

440

}

441

}

442

```

443

444

### Lambda Expression Support

445

446

```java

447

public class LambdaTest {

448

@Test

449

public void testWithLambdas() {

450

new TestKit(system) {{

451

ActorRef actor = system.actorOf(Props.create(ProcessorActor.class));

452

453

// Use lambda for within block

454

String result = (String) within(Duration.ofSeconds(3), () -> {

455

actor.tell("process", getTestActor());

456

return expectMsg(Duration.ofSeconds(2), "processed");

457

});

458

459

// Use lambda for condition waiting

460

awaitCond(Duration.ofSeconds(5), () -> {

461

actor.tell("is-ready", getTestActor());

462

Object response = receiveOne(Duration.ofMillis(100));

463

return "ready".equals(response);

464

});

465

}};

466

}

467

}

468

```

469

470

## Best Practices for Java API

471

472

### Test Structure

473

474

1. **Use TestKit pattern**: Wrap test logic in TestKit anonymous class

475

2. **Proper cleanup**: Always shutdown actor system after tests

476

3. **Use Java 8+ features**: Leverage Duration, Supplier, and lambda expressions

477

4. **Clear assertions**: Use descriptive assertion messages

478

479

```java

480

// Good: Proper test structure

481

public class WellStructuredTest {

482

private static ActorSystem system = ActorSystem.create("TestSystem");

483

484

@Test

485

public void testFeature() {

486

new TestKit(system) {{

487

// Test logic here

488

ActorRef actor = system.actorOf(Props.create(MyActor.class));

489

actor.tell("test", getTestActor());

490

491

String response = (String) expectMsg(Duration.ofSeconds(1), "expected");

492

assertEquals("Should receive correct response", "expected", response);

493

}};

494

}

495

496

@AfterClass

497

public static void cleanup() {

498

TestKit.shutdownActorSystem(system);

499

}

500

}

501

```

502

503

### Error Handling

504

505

1. **Use try-catch blocks**: Handle test exceptions appropriately

506

2. **Provide context**: Include meaningful error messages

507

3. **Test negative cases**: Verify error conditions

508

509

```java

510

// Good: Comprehensive error handling

511

@Test

512

public void testErrorConditions() {

513

new TestKit(system) {{

514

ActorRef actor = system.actorOf(Props.create(FaultyActor.class));

515

516

try {

517

EventFilter.forException(IllegalStateException.class, system)

518

.occurrences(1)

519

.intercept(() -> {

520

actor.tell("invalid-state", getTestActor());

521

return null;

522

});

523

} catch (Exception e) {

524

fail("Expected IllegalStateException was not thrown: " + e.getMessage());

525

}

526

527

// Verify actor recovers

528

actor.tell("valid-request", getTestActor());

529

expectMsg(Duration.ofSeconds(1), "recovered");

530

}};

531

}

532

```

533

534

### Type Safety

535

536

1. **Use typed expectations**: Prefer `expectMsgClass()` over `expectMsg()` when possible

537

2. **Cast carefully**: Use safe casting with instanceof checks

538

3. **Generic types**: Leverage generics where available

539

540

```java

541

// Good: Type-safe testing

542

@Test

543

public void testTypedMessages() {

544

new TestKit(system) {{

545

ActorRef actor = system.actorOf(Props.create(TypedActor.class));

546

547

actor.tell("get-status", getTestActor());

548

StatusMessage status = expectMsgClass(Duration.ofSeconds(1), StatusMessage.class);

549

550

assertNotNull("Status should not be null", status);

551

assertTrue("Status should be active", status.isActive());

552

assertEquals("Count should match", 42, status.getCount());

553

}};

554

}

555

```