testingapache-kafkaquarkussmallryequarkus-reactive

SmallRye InMemoryConnector().clean is not working when running multiple integration test at the same time


Problem :

InMemoryConnector.clear() is not working after running multiple integration tests that publish events at the same time.

My implementation

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@QuarkusTest
@QuarkusTestResource(
    value = InMemReactiveMessagingLifecycleManager::class, initArgs = [
        ResourceArg(value = "incoming", name = "example-processed"),
        ResourceArg(value = "outgoing", name = "example")
    ]
)
class DemoEventProducerTest {

    @Inject
    lateinit var demoEventProducer: demoEventProducer

    @Inject
    @Any
    lateinit var inMemoryConnector: InMemoryConnector

    @Inject
    lateinit var testHelper: TestHelper

    @Test
    fun `publishEvent - valid action - event published`() {
        demoEventProducer.publish()

        val eventQueue = inMemoryConnector.sink<String>("example")
        //event queue contains other events that has been published



      
    }
}
class InMemReactiveMessagingLifecycleManager : QuarkusTestResourceLifecycleManager {

    private val params: MutableMap<String, String> = java.util.HashMap()

    /**
     * Method is invoked before start() method and sets configuration parameters in the class
     */
    override fun init(params: Map<String, String>?) {
        this.params.putAll(params!!)
    }

    override fun start(): Map<String, String> {
        val env: MutableMap<String, String> = HashMap()
        for ((key, value) in params) {
            when (value) {
                "incoming" -> env.putAll(InMemoryConnector.switchIncomingChannelsToInMemory(key))
                "outgoing" -> env.putAll(InMemoryConnector.switchOutgoingChannelsToInMemory(key))
            }
        }
        return env
    }

    override fun stop() {
        InMemoryConnector.clear()
    }
}

Expected behaviour :

val eventQueue = inMemoryConnector.sink<String>("example")

I wanted to clean the queue before this test is running so I will only have exactly one event that this test has produced.

I tried to use @BeforeEach @AfterEeach so that before test method execution I expect the queue is cleaned. but it did not work.


Solution

  • By default test resources are global. During the tests the application starts only once (before all tests) and wont restart until the end except if it is necessary (e.g. a test uses a different test profile). That's because the stop() method of your lifecycle manager will be called during the graceful shutdown phase.

    Additionally InMemoryConnector.clear() will not clear channels / messages. It just switches back the connector name to the original value. To clear messages of a sink you should call clear() method on the sink object after each test like:

    inMemoryConnector.sink<String>("example").clear();