Подождите, пока руководитель не будет готов, прежде чем выполнить тест - PullRequest
0 голосов
/ 03 июля 2019

Я написал тест для своих актеров следующим образом:

class DetectorSpec extends BddSpec {

    private val sap = new SapMock()
        .withExposedPorts(8080)
        .waitingFor(Wait.forHttp("/"))

    private val kafka = new KafkaContainer("5.2.1")


    sap.start()
    kafka.start()


    override def afterAll(): Unit = {
        sap.stop()
        kafka.stop()
    }

    private def withKafkaOfflineSapOnline(testCode: TestProbe[ServerEvent] => Unit)
    : Unit = {

        val config = ConfigFactory.parseString(
        s"""
            kafka {
                servers = "127.0.0.1:9092"
            }
            sap {
                server = "ws://${sap.getContainerIpAddress}:${sap.getMappedPort(8080)}"
            }""")

        val testKit = ActorTestKit("testSystem1", config)
        val inbox = testKit.createTestProbe[ServerEvent]("Receiver")
        testKit.spawn(DetectorSupervisor.create(), "DetectorSupervisor")
        testKit.system.receptionist ! Receptionist.Register(ServerStateKey, inbox.ref)

        Thread.sleep(4000)

        testCode(inbox)
        testKit.shutdownTestKit()
    }


    feature("Detect Kafka and SAP availability") {
        scenario("SAP is online and Kafka is offline") {
        withKafkaOfflineSapOnline { inbox =>
                Given("I am waiting for the current state message")
                When("I am receive the state message")
                val msg = inbox.receiveMessage(3.second)
                Then("it should contain `Kafka is offline`")
                msg should be(ServerOnlineApproved)
            }
        }

    }
}

Как вы можете видеть в методе фикстуры withKafkaOfflineSapOnline, есть утверждение Thread.sleep(4000), чтобы убедиться, что актер DetectorSupervisor с детьми готово до начала теста.

Есть ли лучший способ сделать это?

Без оператора Thread.sleep(4000) кажется, что актеры не готовы, когда начинается тест.

1 Ответ

1 голос
/ 12 июля 2019

Если ваш актер общается только с имитациями, которые вы контролируете напрямую, и вам не нужен реальный параллелизм в тесте, вы можете использовать CallingThreadDispatcherConfigurator.Это имеет смысл, когда вы пишете модульный тест для одного актера или хотите сделать взаимодействие акторов детерминированным в тестах.

Весь асинхронный код будет выполняться в тестовом потоке.Поэтому, отправляя сообщение актеру, вы обычно можете быть уверены, что оно обрабатывается до следующего утверждения вашего теста.

Вот пример того, как создать тестовый набор для этой цели:

val config = ConfigFactory.parseString(
s"""akka.actor.default-dispatcher = {
   |  type = akka.testkit.CallingThreadDispatcherConfigurator
   |}
   |akka.actor.testkit.typed.single-expect-default = 0s
""".stripMargin
)

val testKit = ActorTestKit(ActorTestKitBase.testNameFromCallStack(), config)
...