Akka и Java 8 TestKit на примере

Java 8 и Akka 2.12:2.5.16 здесь. Я пытаюсь написать свой первый (в истории) модульный тест Akka, используя Akka TestKit, и я изо всех сил пытаюсь применить принципы, которые я вижу в (очень немногих) примерах, которые мне удалось найти в Интернете.

Мои актеры:

public class Child extends AbstractActor {
    @Override
    public Receive createReceive() {
        return receiveBuilder()
            .match(Init.class, init -> {
                int workUnit = workService.doSomeWork();
                log.info("Performed work on {}", workUnit);
            }).build();
    }
}

public class Master extends AbstractActor {
    @Inject @Named("CHILD")
    private ActorRef child;

    @Override
    public Receive createReceive() {
        return receiveBuilder()
            .match(Init.class, init -> {
                child.tell(init, self());
            }).build();
    }
}

Очень, очень просто. Так что теперь я просто хочу написать модульные тесты, которые проверяют, что когда Master актор получает Init сообщение, он пересылает это сообщение своему Child актору. Моя лучшая попытка на данный момент:

@RunWith(MockitoJUnitRunner.class)
public class MasterTest {
    private ActorSystem actorSystem;

    @Before
    public void setup() {
        actorSystem = ActorSystem.create("test-system");
    }

    @After
    public void teardown() {
        Duration duration = Duration.create(10L, TimeUnit.SECONDS);
        TestKit.shutdownActorSystem(actorSystem, duration, true);
        actorSystem = null;
    }

    @Test
    public void onInit_shouldSendFordwardToChild() {
        // Given
        TestKit testKit = new TestKit(actorSystem);
        ActorRef master = actorSystem.actorOf(Props.create(Master.class, testKit));

        // When
        master.tell(new Init(), ActorRef.noSender());

        // Then
        testKit.expectMsg(Init.class);
    }
}

Когда я запускаю это, я получаю:

java.lang.IllegalArgumentException: no matching constructor found on class com.me.myapp.Master for arguments [class akka.testkit.TestKit]

Может ли кто-нибудь помочь мне подключить экземпляр TestKit к моему актеру Master, а также помочь мне понять, как реорганизовать MasterTest, чтобы он проверял, чего я пытаюсь достичь? Заранее спасибо!


person hotmeatballsoup    schedule 16.10.2018    source источник


Ответы (1)


Я понял это, не могу поверить, как сложно было заставить это работать :-/

In application.conf:

MyAkkApp {
  akka {
    remote {
      enabled-transports = ["akka.remote.netty.tcp"]
      netty.tcp {
        hostname = "127.0.0.1"
        port = 2553
      }
    }
  }
}

Затем:

@RunWith(MockitoJUnitRunner.class)
public class MasterTest extends TestKit {
    static ActorSystem actorSystem = ActorSystem.create("MyAkkaApp",
        ConfigFactory.load().getConfig("MyAkkaApp"));

    static TestProbe child;  // The mock child
    static ActorRef master;

    @BeforeClass
    public static void setup() {
        child = new TestProbe(actorSystem, "Child");
        master = actorSystem.actorOf(Props.create(new Creator<Actor>() {
            @Override
            public Actor create() throws Exception {
                return new Master(child.ref());
            }
        }));
    }

    public MasterTest() {
        super(actorSystem);
    }

    @Test
    public void onInit_shouldSendFordwardToChild() {
        // Given
        Init init = new Init();

        // When
        master.tell(init, super.testActor());

        // Then
        child.expectMsg(init);  // Child should have received it
        expectNoMessage();  // Master should not be returning to sender
    }
}

Давай, Акка, ребята! Поддержка приводит к внедрению, внедрение ведет к стандартизации, стандартизация означает, что вы можете продавать корпоративные лицензии на поддержку с шестизначной суммой.

person hotmeatballsoup    schedule 18.10.2018
comment
Я не уверен, почему вам пришлось вносить какие-либо изменения в конфигурацию транспорта; Я не вижу никакого удаленного взаимодействия. Кроме того, в чем проблема? Akka не выполняет внедрение зависимостей; когда у меня были актеры родитель-потомок, я буквально создал дочерний элемент из родителя (getContext().actorOf(...)), и для тестирования я изолировал это в своем собственном методе, подклассе тестируемого актера и вернуть тестовый щуп. - person Rob Crawford; 07.11.2018
comment
Спасибо, @RobCrawford. Мне с удовольствием хотелось бы увидеть образец одного из ваших модульных тестов Akka TestKit... - person hotmeatballsoup; 29.01.2019