Coroutine tests break automatically assigned id for ObjectBox Entity in Kotlin Jetpack Compose

29 views Asked by At

I'm running a set of tests on the database using .directory(TEST_DIRECTORY) as instructed in the docs. There's a setUp() and a tearDown() for @Before and @After, respectively.

I test the following cases:

  1. queries on the database return empty lists for all three suspend functions declared in the interface
  2. for each suspend function, I test the outcome

What is strange is the following:

  1. the empty lists queries succeed
  2. out of the three functions that suppose to return an entity populated object, two of them fail and one of them succeeds

This makes me wonder: is there a possibility that the setUp() and tearDown() don't work as expected?

The error I get is the following:

java.lang.IllegalArgumentException: ID is higher or equal to internal ID sequence: 1 (vs. 1). Use ID 0 (zero) to insert new entities.

for both of the failing test cases (to reiterate: one of them is succeeding so the population of entities in the database works as expected for this [always] one test case but fails [always] for the other two test cases).

In an object I declare a list of Entity instantiations with the id set to 0L (the default) of the form:

object MyEntitiesMockDataSource {

    ...

    val entityList = listOf(
        MyEntity(
            parameterOne = "someValueOne",
            parameterTwo = someValueOne,
            parameterThree = someValueOne
        ),
        MyEntity(
            parameterOne = "someValueTwo",
            parameterTwo = someValueTwo,
            parameterThree = someValueTwo
        ),
        MyEntity(
            parameterOne = "someValueThree",
            parameterTwo = someValueThree,
            parameterThree = someValueThree
        ),
        ...
}

in total of 10 MyEntity objects.

The tests are in the form of:

    @Test
    fun testGetLatest10EntitiesByOwner_populatedBox_emitsExpectedEntitiesByOwner() = runTest {
        val owner = "[email protected]"
        val entities = MyEntityMockDataSource.entityList

        /** Insert test entities into the database */
        boxStore.boxFor<MyEntity>().put(entities)

        repository.getLatest10EntitiesByOwner(owner).test {
            val emission = awaitItem()
            awaitComplete()
            /** reversed() because the query does orderDesc() */
            assertEquals(entities.reversed(), emission)
        }
    }

Could it be possible that ObjectBox somehow doesn't delete the database and it then fails after first successful execution of the first (non empty) test case and then hits the second and the third but there're already entities instantiated and thus the ID generation now fails?

How could this be even when the id is set to 0L? Or is it because of the suspend functions? Should I just use regular functions? Will ObjectBox run them asynchronously in Dispatcher.IO thread?

I do not want to set @Id(assignable = true) - I'm sure there's a way to make the tests work without setting assignable to true.

0

There are 0 answers