I'm moving first steps in AKKA by following this guide: there is a J-unit test file and a class for the Actor. You can see the whole code at the link, it's just a bunch of lines.
However test fails with a NullPointerException
trying to build the new TestKit, and this is the error reported in the failure trace view(Eclipse):
java.lang.NullPointerException
at akka.actor.ExtensionId.apply(Extension.scala:77)
at akka.actor.ExtensionId.apply$(Extension.scala:77)
at akka.testkit.TestKitExtension$.apply(TestKitExtension.scala:11)
at akka.testkit.TestKitBase.$init$(TestKit.scala:145)
at akka.testkit.TestKit.<init>(TestKit.scala:828)
at akka.testkit.TestProbe.<init>(TestKit.scala:886)
at akka.testkit.TestProbe.<init>(TestKit.scala:888)
at akka.testkit.javadsl.TestKit.<init>(TestKit.scala:43)
at com.lightbend.akka.sample.DeviceTest.testReplyWithLatestTemperatureReading(DeviceTest.java:16)
What is this about?
[edit]
The question you linked is useful to understand the meaning of the Exception, but I am still not able to find where it occurs in my code.
Here, when junit calls the new TestKit(system)
fails:
package com.lightbend.akka.sample;
import static org.junit.Assert.assertEquals;
import java.util.Optional;
import org.junit.Test;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.testkit.javadsl.TestKit;
public class DeviceTest {
static ActorSystem system;
@Test
public void testReplyWithLatestTemperatureReading() {
TestKit probe = new TestKit(system);
ActorRef deviceActor = system.actorOf(Device.props("group", "device"));
deviceActor.tell(new Device.RecordTemperature(1L, 24.0), probe.getRef());
assertEquals(1L, probe.expectMsgClass(Device.TemperatureRecorded.class).requestId);
deviceActor.tell(new Device.ReadTemperature(2L), probe.getRef());
Device.RespondTemperature response1 = probe.expectMsgClass(Device.RespondTemperature.class);
assertEquals(2L, response1.requestId);
assertEquals(Optional.of(24.0), response1.value);
deviceActor.tell(new Device.RecordTemperature(3L, 55.0), probe.getRef());
assertEquals(3L, probe.expectMsgClass(Device.TemperatureRecorded.class).requestId);
deviceActor.tell(new Device.ReadTemperature(4L), probe.getRef());
Device.RespondTemperature response2 = probe.expectMsgClass(Device.RespondTemperature.class);
assertEquals(4L, response2.requestId);
assertEquals(Optional.of(55.0), response2.value);
}
}
And this is the complete Actor code:
package com.lightbend.akka.sample;
import java.util.Optional;
import akka.actor.AbstractActor;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class Device extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
final String groupId;
final String deviceId;
public Device(String groupId, String deviceId) {
this.groupId = groupId;
this.deviceId = deviceId;
}
public static Props props(String groupId, String deviceId) {
return Props.create(Device.class, groupId, deviceId);
}
public static final class RecordTemperature {
final long requestId;
final double value;
public RecordTemperature(long requestId, double value) {
this.requestId = requestId;
this.value = value;
}
}
public static final class TemperatureRecorded {
final long requestId;
public TemperatureRecorded(long requestId) {
this.requestId = requestId;
}
}
public static final class ReadTemperature {
final long requestId;
public ReadTemperature(long requestId) {
this.requestId = requestId;
}
}
public static final class RespondTemperature {
final long requestId;
final Optional<Double> value;
public RespondTemperature(long requestId, Optional<Double> value) {
this.requestId = requestId;
this.value = value;
}
}
Optional<Double> lastTemperatureReading = Optional.empty();
@Override
public void preStart() {
log.info("Device actor {}-{} started", groupId, deviceId);
}
@Override
public void postStop() {
log.info("Device actor {}-{} stopped", groupId, deviceId);
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(RecordTemperature.class, r -> {
log.info("Recorded temperature reading {} with {}", r.value, r.requestId);
lastTemperatureReading = Optional.of(r.value);
getSender().tell(new TemperatureRecorded(r.requestId), getSelf());
})
.match(ReadTemperature.class, r -> {
getSender().tell(new RespondTemperature(r.requestId, lastTemperatureReading), getSelf());
})
.build();
}
}
Maybe the problem is that system
is still not initialized? I tried to manage it, but I'm not going anywhere.