4

I'm trying to write a test for one of my repositories, but I' can't save my Entity object due to the following error:

java.lang.IllegalStateException: ToOne object is null inside br.com.CalendarEvent

My Entities are these two:

@Entity
data class CalendarEvent(
    @Id var boxId: Long = 0,

    @Index var id: String = UUID.randomUUID().toString(),

    var userId: String = "",

    var title: String = "",

    var discipline: String = "",

    var hour: Int = 1,

    var dateInEpochDay: Long = 0L,

    var isOnline: Boolean = false,

    var estimatedTime: Int = 1,

    var userAttended: Boolean? = null) {

    lateinit var nucleus: ToOne<SupportNucleus>

    lateinit var specialNeeds: ToMany<SpecialNeed>

}
@Entity
data class SupportNucleus(
@Id var boxId: Long = 0,

@Index var id: String = UUID.randomUUID().toString(),

var name: String = "",

var location: String = "",

var contact: String = "",

var phones: String = "",

var startWorkingHour: Int = 9,

var endWorkingHour: Int = 23,

@Transient var unavailableDays: List<Long> = listOf())

As you can see both entities have their no-arg constructors, and I works as fine when I'm saving an CalendarEvent running the app or running an instrumented test. This error only occurs on Local Unit Test

My test class:

class CalendarBoxRepositoryTest : BaseObjectBoxTest() {

    lateinit var subjectRepository: CalendarRepository

    var dataSourceMock: CalendarDataSource = mockk()
    var dataMapperMock: CalendarDataMapper = mockk()

    @Before
    fun setup() {
        subjectRepository = CalendarBox(dataSourceMock)
    }


    @Test
    fun save_calendar_event_correctly() {
        //Given no event was saved
        val calendarBoxBefore = store?.boxFor(CalendarEvent::class.java)
        assertEquals(0, calendarBoxBefore?.all?.size)

        val calendar = CalendarEvent(userId = "userId", title = "Title", discipline = "Discipline",
            dateInEpochDay = 123, isOnline = false, estimatedTime = 1, userAttended = null)

        val nucleus = SupportNucleus(name = "Support")


        calendar.nucleus = ToOne(calendar, CalendarEvent_.nucleus)
        calendar.nucleus.target = nucleus

        //When Saved
        runBlocking {
            subjectRepository.saveCalendarEvent(calendar)
        }

        //Verify saved correctly
        val calendarBoxAfter = store?.boxFor(CalendarEvent::class.java)
        assertEquals(1, calendarBoxAfter?.all?.size)
    }
}

The error actually occurs when I'm trying to fetch after saving to assert that it was saved correctly btw.

julioribeiro
  • 1,565
  • 2
  • 14
  • 22
  • Have you seen https://docs.objectbox.io/android/android-local-unit-tests and specifically https://docs.objectbox.io/android/android-local-unit-tests#testing-entities-with-relations ? – Markus Junginger Dec 17 '19 at 09:20
  • Yes, that's why I've added this lines: calendar.nucleus = ToOne(calendar, CalendarEvent_.nucleus) calendar.nucleus.target = nucleus Am I missing something? – julioribeiro Dec 18 '19 at 12:12

1 Answers1

3

Try to remove lateinit from the ToOne and immediately initialize it:

@Entity
data class CalendarEvent(
...
    ) {

    var nucleus = ToOne<SupportNucleus>(this, CalendarEvent_.nucleus)

}

Note: The ToOne/ToMany initialization is no longer required for Android projects since ObjectBox 1.5 or newer when running tests from Android Studio or directly running the Gradle task, e.g. testDebugUnitTest.

Check if a Gradle task like objectboxTransformDebugUnitTest runs before the test task (which it is setup to by default).

Uwe - ObjectBox
  • 1,012
  • 1
  • 7
  • 11
  • 1
    Thank you, worked like a charm! I suggest changed to this on relations page of ObjectBox as well https://docs.objectbox.io/relations – julioribeiro Jan 07 '20 at 13:03
  • I should also add that now a warning is showing in console: CalendarEvent constructor initializes relation field 'nucleus', this might break ObjectBox relations. Should I worry about it? – julioribeiro Jan 07 '20 at 13:19
  • That warning is interesting. It means the byte code transformer actually is running and detects that the ToOne is already being initialized. In this case it is safe to ignore, as it is done on purpose. Is it possible for you to share a minimal example project so we can check why the transformer does not inject the ToOne initialization? – Uwe - ObjectBox Jan 13 '20 at 06:51