0
# Java DSL
1
2
Complete Java API providing equivalent functionality to the Scala API with Java-friendly method signatures and type usage.
3
4
## Capabilities
5
6
### javadsl.TestKit Class
7
8
Java API for TestKit functionality with Java-friendly types and method signatures.
9
10
```scala { .api }
11
package akka.testkit.javadsl
12
13
class TestKit(system: ActorSystem) {
14
// Message expectation methods
15
def expectMsg(msg: Object): Object
16
def expectMsg(max: java.time.Duration, msg: Object): Object
17
def expectMsgClass[T](c: Class[T]): T
18
def expectMsgClass[T](max: java.time.Duration, c: Class[T]): T
19
def expectMsgAnyOf(objects: Object*): Object
20
def expectMsgAnyOf(max: java.time.Duration, objects: Object*): Object
21
def expectMsgAllOf(objects: Object*): java.util.List[Object]
22
def expectMsgAllOf(max: java.time.Duration, objects: Object*): java.util.List[Object]
23
def expectNoMessage(): Unit
24
def expectNoMessage(max: java.time.Duration): Unit
25
26
// Message reception methods
27
def receiveN(n: Int): java.util.List[Object]
28
def receiveN(n: Int, max: java.time.Duration): java.util.List[Object]
29
def receiveOne(max: java.time.Duration): Object
30
31
// Timing and condition methods
32
def within[T](max: java.time.Duration, f: Supplier[T]): T
33
def within[T](min: java.time.Duration, max: java.time.Duration, f: Supplier[T]): T
34
def awaitCond(p: Supplier[java.lang.Boolean]): Unit
35
def awaitCond(p: Supplier[java.lang.Boolean], max: java.time.Duration): Unit
36
def awaitCond(p: Supplier[java.lang.Boolean], max: java.time.Duration, interval: java.time.Duration): Unit
37
def awaitAssert[A](a: Supplier[A]): A
38
def awaitAssert[A](a: Supplier[A], max: java.time.Duration): A
39
def awaitAssert[A](a: Supplier[A], max: java.time.Duration, interval: java.time.Duration): A
40
41
// Actor management methods
42
def watch(ref: ActorRef): ActorRef
43
def unwatch(ref: ActorRef): ActorRef
44
def childActorOf(props: Props): ActorRef
45
def childActorOf(props: Props, name: String): ActorRef
46
47
// Properties
48
def getTestActor(): ActorRef
49
def getSystem(): ActorSystem
50
def duration(s: String): java.time.Duration
51
def dilated(d: java.time.Duration): java.time.Duration
52
}
53
```
54
55
**Usage Example:**
56
57
```java
58
import akka.actor.*;
59
import akka.testkit.javadsl.TestKit;
60
import org.junit.Test;
61
import org.junit.AfterClass;
62
import org.junit.BeforeClass;
63
import java.time.Duration;
64
65
public class JavaTestKitExample {
66
static ActorSystem system;
67
68
@BeforeClass
69
public static void setup() {
70
system = ActorSystem.create("TestSystem");
71
}
72
73
@AfterClass
74
public static void teardown() {
75
TestKit.shutdownActorSystem(system);
76
system = null;
77
}
78
79
// Simple echo actor for testing
80
static class EchoActor extends AbstractActor {
81
@Override
82
public Receive createReceive() {
83
return receiveBuilder()
84
.matchAny(msg -> getSender().tell(msg, getSelf()))
85
.build();
86
}
87
}
88
89
@Test
90
public void testEchoActor() {
91
new TestKit(system) {{
92
final ActorRef echoActor = system.actorOf(Props.create(EchoActor.class));
93
94
// Basic message expectation
95
echoActor.tell("hello", getTestActor());
96
expectMsg("hello");
97
98
// Expectation with timeout
99
echoActor.tell(42, getTestActor());
100
expectMsg(Duration.ofSeconds(3), 42);
101
102
// Expect specific type
103
echoActor.tell("test", getTestActor());
104
expectMsgClass(String.class);
105
106
// Multiple messages
107
echoActor.tell("first", getTestActor());
108
echoActor.tell("second", getTestActor());
109
expectMsgAllOf("first", "second");
110
}};
111
}
112
113
@Test
114
public void testTimingAndConditions() {
115
new TestKit(system) {{
116
final boolean[] condition = {false};
117
118
// Schedule condition to become true
119
system.scheduler().scheduleOnce(
120
Duration.ofMillis(500),
121
() -> condition[0] = true,
122
system.dispatcher()
123
);
124
125
// Wait for condition
126
awaitCond(() -> condition[0], Duration.ofSeconds(2));
127
128
// Time-bounded execution
129
within(Duration.ofSeconds(1), () -> {
130
expectNoMessage(Duration.ofMillis(100));
131
return null;
132
});
133
}};
134
}
135
}
136
```
137
138
### javadsl.EventFilter Class
139
140
Java API for event filtering with builder-style methods.
141
142
```scala { .api }
143
package akka.testkit.javadsl
144
145
class EventFilter {
146
// Execution methods
147
def intercept[T](code: Supplier[T]): T
148
def intercept(code: Runnable): Unit
149
150
// Configuration methods (return new EventFilter for chaining)
151
def message(msg: String): EventFilter
152
def startsWith(msg: String): EventFilter
153
def matches(regex: String): EventFilter
154
def from(source: String): EventFilter
155
def occurrences(number: Int): EventFilter
156
157
// Static factory methods
158
static EventFilter error(): EventFilter
159
static EventFilter error(Class[_ <: Throwable] clazz): EventFilter
160
static EventFilter warning(): EventFilter
161
static EventFilter info(): EventFilter
162
static EventFilter debug(): EventFilter
163
static EventFilter custom(Function[LogEvent, java.lang.Boolean] test): EventFilter
164
}
165
```
166
167
**Usage Example:**
168
169
```java
170
import akka.testkit.javadsl.EventFilter;
171
import akka.event.Logging;
172
173
public class JavaEventFilterExample {
174
@Test
175
public void testEventFiltering() {
176
new TestKit(system) {{
177
// Simple error filtering
178
EventFilter.error()
179
.message("Expected error")
180
.occurrences(1)
181
.intercept(() -> {
182
ActorRef actor = system.actorOf(Props.create(ThrowingActor.class));
183
actor.tell("throw", getTestActor());
184
});
185
186
// Warning filtering with pattern
187
EventFilter.warning()
188
.matches("User \\d+ logged in")
189
.intercept(() -> {
190
// Code that logs user login messages
191
});
192
193
// Custom filtering
194
EventFilter.custom(event ->
195
event instanceof Logging.Error &&
196
event.message().toString().contains("database")
197
).intercept(() -> {
198
// Code that generates database errors
199
});
200
201
// Multiple filters (using separate calls)
202
EventFilter.error().occurrences(1).intercept(() -> {
203
EventFilter.warning().startsWith("Deprecated").intercept(() -> {
204
// Code that generates both errors and warnings
205
});
206
});
207
}};
208
}
209
}
210
```
211
212
### Java Functional Interfaces Integration
213
214
TestKit integrates well with Java 8+ functional interfaces:
215
216
```java
217
import java.util.function.*;
218
import java.util.concurrent.CompletableFuture;
219
220
public class JavaFunctionalExample {
221
@Test
222
public void testWithLambdas() {
223
new TestKit(system) {{
224
// Using lambdas with awaitCond
225
CompletableFuture<String> future = CompletableFuture
226
.supplyAsync(() -> "result")
227
.thenApplyAsync(s -> s.toUpperCase());
228
229
awaitCond(() -> future.isDone(), Duration.ofSeconds(2));
230
231
// Using method references
232
Consumer<String> sendToActor = msg ->
233
getTestActor().tell(msg, ActorRef.noSender());
234
235
within(Duration.ofSeconds(1), () -> {
236
sendToActor.accept("test message");
237
expectMsg("test message");
238
return null;
239
});
240
241
// Functional event filtering
242
EventFilter.custom(event ->
243
event.logLevel().equals(Logging.InfoLevel()) &&
244
event.toString().contains("important")
245
).intercept(() -> {
246
// Code that generates important info messages
247
});
248
}};
249
}
250
}
251
```
252
253
### Java Collections Integration
254
255
TestKit methods return Java collections where appropriate:
256
257
```java
258
import java.util.*;
259
260
public class JavaCollectionsExample {
261
@Test
262
public void testCollections() {
263
new TestKit(system) {{
264
ActorRef actor = system.actorOf(Props.create(EchoActor.class));
265
266
// Send multiple messages
267
List<String> messages = Arrays.asList("msg1", "msg2", "msg3");
268
messages.forEach(msg -> actor.tell(msg, getTestActor()));
269
270
// Receive as Java List
271
List<Object> received = receiveN(3, Duration.ofSeconds(2));
272
273
// Convert and verify
274
List<String> receivedStrings = received.stream()
275
.map(Object::toString)
276
.collect(java.util.stream.Collectors.toList());
277
278
assertEquals(messages, receivedStrings);
279
280
// Expect multiple messages (returns Java List)
281
actor.tell("a", getTestActor());
282
actor.tell("b", getTestActor());
283
List<Object> results = expectMsgAllOf(Duration.ofSeconds(1), "a", "b");
284
285
assertEquals(2, results.size());
286
assertTrue(results.contains("a"));
287
assertTrue(results.contains("b"));
288
}};
289
}
290
}
291
```
292
293
### Exception Handling in Java DSL
294
295
```java
296
public class JavaExceptionHandlingExample {
297
@Test
298
public void testExceptionHandling() {
299
new TestKit(system) {{
300
// Handle timeout exceptions
301
try {
302
expectMsg(Duration.ofMillis(100), "never-sent");
303
fail("Should have timed out");
304
} catch (AssertionError e) {
305
// Expected timeout
306
assertTrue(e.getMessage().contains("timeout"));
307
}
308
309
// Test actor failures with event filtering
310
EventFilter.error(RuntimeException.class)
311
.message("Test exception")
312
.intercept(() -> {
313
ActorRef actor = system.actorOf(Props.create(FailingActor.class));
314
actor.tell("fail", getTestActor());
315
});
316
}};
317
}
318
319
static class FailingActor extends AbstractActor {
320
@Override
321
public Receive createReceive() {
322
return receiveBuilder()
323
.matchEquals("fail", msg -> {
324
throw new RuntimeException("Test exception");
325
})
326
.build();
327
}
328
}
329
}
330
```
331
332
### Integration with JUnit and TestNG
333
334
**JUnit Integration:**
335
336
```java
337
import org.junit.*;
338
import org.junit.rules.TestName;
339
340
public class JUnitIntegrationExample {
341
private static ActorSystem system;
342
private TestKit testKit;
343
344
@Rule
345
public TestName testName = new TestName();
346
347
@BeforeClass
348
public static void setupClass() {
349
system = ActorSystem.create("TestSystem");
350
}
351
352
@Before
353
public void setup() {
354
testKit = new TestKit(system);
355
}
356
357
@After
358
public void cleanup() {
359
// Individual test cleanup if needed
360
}
361
362
@AfterClass
363
public static void teardownClass() {
364
TestKit.shutdownActorSystem(system);
365
}
366
367
@Test
368
public void testActorBehavior() {
369
// Use testKit for testing
370
ActorRef actor = system.actorOf(Props.create(MyActor.class),
371
"actor-" + testName.getMethodName());
372
373
actor.tell("test", testKit.getTestActor());
374
testKit.expectMsg("response");
375
}
376
}
377
```
378
379
**TestNG Integration:**
380
381
```java
382
import org.testng.annotations.*;
383
384
public class TestNGIntegrationExample {
385
private ActorSystem system;
386
private TestKit testKit;
387
388
@BeforeClass
389
public void setupClass() {
390
system = ActorSystem.create("TestSystem");
391
}
392
393
@BeforeMethod
394
public void setup() {
395
testKit = new TestKit(system);
396
}
397
398
@AfterClass
399
public void teardownClass() {
400
TestKit.shutdownActorSystem(system);
401
}
402
403
@Test
404
public void testExample() {
405
// TestNG test using TestKit
406
testKit.within(Duration.ofSeconds(2), () -> {
407
// Test code
408
return null;
409
});
410
}
411
}
412
```
413
414
### Best Practices for Java DSL
415
416
1. **Use Java 8+ Features**: Leverage lambdas, streams, and method references
417
2. **Handle Timeouts**: Always specify reasonable timeouts for expectations
418
3. **Resource Management**: Use try-with-resources or proper cleanup
419
4. **Type Safety**: Use generic methods where available for type safety
420
5. **Integration**: Combine with testing frameworks like JUnit/TestNG
421
422
```java
423
// Good: Use lambdas and proper timeouts
424
testKit.awaitCond(() -> actor.isTerminated(), Duration.ofSeconds(3));
425
426
// Good: Type-safe message expectations
427
String response = testKit.expectMsgClass(Duration.ofSeconds(1), String.class);
428
429
// Good: Functional event filtering
430
EventFilter.custom(event -> event.logLevel().equals(Logging.ErrorLevel()))
431
.intercept(() -> triggerError());
432
433
// Good: Resource cleanup
434
@After
435
public void cleanup() {
436
if (testKit != null) {
437
// Clean up test resources
438
}
439
}
440
```