首页 > 解决方案 > Akka testkit 类型不编译

问题描述

我正在尝试使用以下代码使用 Testkit 设置一个简单的 Akka 测试:

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.Scheduler;
import akka.actor.typed.javadsl.AskPattern;
import akka.actor.typed.javadsl.Behaviors;
// #test-header

//import akka.actor.testkit.typed.javadsl.*;

import akka.actor.testkit.typed.javadsl.TestInbox;
// #test-header
import akka.actor.testkit.typed.javadsl.TestProbe;
import org.junit.AfterClass;
import org.junit.Test;
import org.scalatestplus.junit.JUnitSuite;

import java.time.Duration;
import java.util.concurrent.CompletionStage;
import java.util.stream.IntStream;

import java.util.Objects;

import static org.junit.Assert.assertEquals;

// #test-header
public class AsyncTestingExampleTest
        // #test-header
        extends JUnitSuite
// #test-header
{
    static final ActorTestKit testKit = ActorTestKit.create();
    // #test-header

    // #under-test
    public static class Echo {
        public static class Ping {
            public final String message;
            public final ActorRef<Pong> replyTo;

            public Ping(String message, ActorRef<Pong> replyTo) {
                this.message = message;
                this.replyTo = replyTo;
            }
        }

        public static class Pong {
            public final String message;

            public Pong(String message) {
                this.message = message;
            }

            @Override
            public boolean equals(Object o) {
                if (this == o) return true;
                if (!(o instanceof Pong)) return false;
                Pong pong = (Pong) o;
                return message.equals(pong.message);
            }

            @Override
            public int hashCode() {
                return Objects.hash(message);
            }
        }

        public static Behavior<Ping> create() {
            return Behaviors.receive(Ping.class)
                    .onMessage(
                            Ping.class,
                            ping -> {
                                ping.replyTo.tell(new Pong(ping.message));
                                return Behaviors.same();
                            })
                    .build();
        }
    }
    // #under-test

    // #under-test-2

    static class Message {
        int i;
        ActorRef<Integer> replyTo;

        Message(int i, ActorRef<Integer> replyTo) {
            this.i = i;
            this.replyTo = replyTo;
        }
    }

    public static class Producer {

        private Scheduler scheduler;
        private ActorRef<Message> publisher;

        Producer(Scheduler scheduler, ActorRef<Message> publisher) {
            this.scheduler = scheduler;
            this.publisher = publisher;
        }

        public void produce(int messages) {
            IntStream.range(0, messages).forEach(this::publish);
        }

        private CompletionStage<Integer> publish(int i) {
            return AskPattern.ask(
                    publisher,
                    (ActorRef<Integer> ref) -> new Message(i, ref),
                    Duration.ofSeconds(3),
                    scheduler);
        }
    }
    // #under-test-2

    // #test-shutdown
    @AfterClass
    public static void cleanup() {
        testKit.shutdownTestKit();
    }
    // #test-shutdown

    @Test
    public void testVerifyingAResponse() {
        // #test-spawn
        ActorRef<Echo.Ping> pinger = testKit.spawn(Echo.create(), "ping");
        TestProbe<Echo.Pong> probe = testKit.createTestProbe();
        pinger.tell(new Echo.Ping("hello", probe.ref()));
        probe.expectMessage(new Echo.Pong("hello"));
        // #test-spawn
    }

    @Test
    public void testVerifyingAResponseAnonymous() {
        // #test-spawn-anonymous
        ActorRef<Echo.Ping> pinger = testKit.spawn(Echo.create());
        // #test-spawn-anonymous
        TestProbe<Echo.Pong> probe = testKit.createTestProbe();
        pinger.tell(new Echo.Ping("hello", probe.ref()));
        probe.expectMessage(new Echo.Pong("hello"));
    }

    @Test
    public void testStoppingActors() {
        TestProbe<Echo.Pong> probe = testKit.createTestProbe();
        // #test-stop-actors
        ActorRef<Echo.Ping> pinger1 = testKit.spawn(Echo.create(), "pinger");
        pinger1.tell(new Echo.Ping("hello", probe.ref()));
        probe.expectMessage(new Echo.Pong("hello"));
        testKit.stop(pinger1);

        // Immediately creating an actor with the same name
        ActorRef<Echo.Ping> pinger2 = testKit.spawn(Echo.create(), "pinger");
        pinger2.tell(new Echo.Ping("hello", probe.ref()));
        probe.expectMessage(new Echo.Pong("hello"));
        testKit.stop(pinger2, Duration.ofSeconds(10));
        // #test-stop-actors
    }

    @Test
    public void testObserveMockedBehavior() {
        // #test-observe-mocked-behavior
        // simulate the happy path
        Behavior<Message> mockedBehavior =
                Behaviors.receiveMessage(
                        message -> {
                            message.replyTo.tell(message.i);
                            return Behaviors.same();
                        });
        TestProbe<Message> probe = testKit.createTestProbe();
        ActorRef<Message> mockedPublisher =
                testKit.spawn(Behaviors.monitor(Message.class, probe.ref(), mockedBehavior));

        // test our component
        Producer producer = new Producer(testKit.scheduler(), mockedPublisher);
        int messages = 3;
        producer.produce(messages);

        // verify expected behavior
        IntStream.range(0, messages)
                .forEach(
                        i -> {
                            Message msg = probe.expectMessageClass(Message.class);
                            assertEquals(i, msg.i);
                        });
        // #test-observe-mocked-behavior
    }

    @Test
    public void systemNameShouldComeFromTestClass() {
        assertEquals(testKit.system().name(), "AsyncTestingExampleTest");
    }
    // #test-header
}
// #test-header

此代码基于:https ://doc.akka.io/docs/akka/current/typed/testing-async.html#configuration

相关代码的依赖 pom.xml 是:

这是使用来自https://doc.akka.io/docs/akka/current/typed/testing-async.html#configuration的 Akka Testkit 依赖项

<properties>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <scala.binary.version>2.13</scala.binary.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-bom_${scala.binary.version}</artifactId>
            <version>2.6.14</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.typesafe.akka</groupId>
        <artifactId>akka-stream_2.13</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.3.3</version>
    </dependency>
    <dependency>
        <groupId>com.typesafe.akka</groupId>
        <artifactId>akka-actor-typed_${scala.binary.version}</artifactId>
    </dependency>
    <dependency>
        <groupId>com.typesafe.akka</groupId>
        <artifactId>akka-actor-testkit-typed_${scala.binary.version}</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

问题是编译器没有找到一些导入的类,例如:

import akka.actor.testkit.typed.javadsl.TestInbox;
// #test-header
import akka.actor.testkit.typed.javadsl.TestProbe;
import org.junit.AfterClass;
import org.junit.Test;
import org.scalatestplus.junit.JUnitSuite

并且对于上述每个类都失败并出现错误“无法解析符号”。

我已经尝试清除我的 Maven 依赖项,但似乎我没有正确设置依赖项。

为了使用 Akka Typed Testkit for Java,是否还需要其他依赖项?

标签: javascalaakkaakka-testkit

解决方案


答案现在如此明显。我忽略了一个事实,即我正在从非测试目录执行测试代码,并且由于测试依赖项的范围是测试,因此这些库不可用。此外,我在这里的答案是“睡在上面”。


推荐阅读