Wait until the supervisor is ready before execute the test

Hi all

I have written a test for my actors as follows:

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)
            }
        }

    }
}

As you can see in the fixture method withKafkaOfflineSapOnline , there is a statement Thread.sleep(4000) to make it sure, that actor DetectorSupervisor with they children is ready before the test get started.

Is there a better way to do it?

Without the Thread.sleep(4000) statement, it seems to be, that the actors are not ready, when the test is starting.

Thanks

The best way to do it would probably be to change your DetectorSupervisor implementation to stash all incoming messages at first, and then unstash all messages once the children are ready.

That way the test (or any other sender) doesn’t have to wait for the actor to be ready, it can start sending messages right away. The actor itself is responsible for handling them when it’s ready.

There’s an example here:

https://doc.akka.io/docs/akka/current/typed/stash.html

1 Like