0

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.

Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
glc78
  • 439
  • 1
  • 8
  • 20
  • https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it – Krease Mar 16 '18 at 21:06
  • Your code doesn't show how you are creating the actor system. See the example here and notice the @BeforeClass method: https://doc.akka.io/docs/akka/current/testing.html#asynchronous-testing-testkit – Michal Borowiecki Mar 17 '18 at 10:37
  • @MichalBorowiecki I wasn't writing the Actor code because it's exactly the same of the guide I linked. However I'm going to edit and write down the code in the question if this can help. – glc78 Mar 17 '18 at 10:58
  • 1
    Well, the code you posted is not creating the actor system anywhere. It seems the guide missed that part. Follow the longer example of a JUnit test class here: https://doc.akka.io/docs/akka/current/testing.html#asynchronous-testing-testkit and notice how the ActorSystem is being created in the "@BeforeClass" and shut down in the "@AfterClass" – Michal Borowiecki Mar 17 '18 at 11:40
  • @MichalBorowiecki Maybe the guide creates the Actor in the previous pages. However the code you provided is more clear with me, thanks. – glc78 Mar 17 '18 at 13:32

0 Answers0