App runs as it should. But when unit testing, I get the warning and fail messages (below) on the entity with ToOne relation to other entity.
I do not see how I initialize the relation field in the constructor.
Similar to https://github.com/objectbox/objectbox-java/issues/179, but I do not use JaCoCo.
./gradlew :data:testDebugUnitTest
Project on github: https://github.com/deividasstr/sweets-counter
Task :data:transformClassesWithObjectBoxAndroidTransformForDebug FAILED
Warning: com.deividasstr.data.store.models.ConsumedSweetDb constructor initializes relation field 'sweet', this might break ObjectBox relations
Could not transform Cursor class "com.deividasstr.data.store.models.ConsumedSweetDbCursor" (Expected empty method body for com.deividasstr.data.store.models.ConsumedSweetDbCursor.attachEntity but was 9 long)
@Entity
data class ConsumedSweetDb(
@Id var id: Long,
val sweetId: Long, // id of related entity
val g: Long,
val date: Long
) {
constructor(sweet: ConsumedSweet) : this(sweet.id, sweet.sweetId, sweet.g, sweet.date)
// secondary convenience constructor for transformation
lateinit var sweet: ToOne<SweetDb>
val sweetDb: SweetDb // convenience getter
get() = sweet.target
}
Thanks for reporting!
OK, looks like for Android library projects transformations do run for unit tests. Unlike for Android application projects.
Which is why we manually run our transform task when unit tests are compiled. For Android library projects this then leads to the transformer running twice, which fails:
> Task :data:objectboxTransformDebugUnitTest
Transformed 2 entities and copied 112 classes in 15 ms
> Task :data:compileDebugUnitTestJavaWithJavac NO-SOURCE
> Task :data:processDebugUnitTestJavaRes NO-SOURCE
> Task :data:processDebugJavaRes NO-SOURCE
> Task :data:transformClassesWithObjectBoxAndroidTransformForDebug FAILED
Warning: com.deividasstr.data.store.models.ConsumedSweetDb constructor initializes relation field 'sweet', this might break ObjectBox relations
Could repro this using our test projects as well (requires adding a ToOne to the test entity + unit test):
> Task :test-kotlin-android-library:javaPreCompileDebugUnitTest
> Task :test-kotlin-android-library:objectboxTransformDebugUnitTest
[...]
Transformed 2 entities and copied 14 classes in 46 ms
> Task :test-kotlin-android-library:compileDebugUnitTestJavaWithJavac NO-SOURCE
> Task :test-kotlin-android-library:transformClassesWithObjectBoxAndroidTransformForDebug FAILED
Warning: io.objectbox.kotlin.android.library.LibEntity constructor initializes relation field 'libEntity', this might break ObjectBox relations
This is really odd behavior. Why would transformers run for Android library project unit tests, but not for app project unit tests? Will look into updating the plugin to handle this.
Update: transformers only run when running with Gradle. Right-lick and running tests in Android Studio still does not run transforms sigh. See related #240.
-ut
@deividasstr Until a fix is out you can work around this by explicitly excluding the ObjectBox transform task:
~gradlew :data:testDebugUnitTest -x objectboxTransformDebugUnitTest~
Edit: dang, this now causes NPE on ToOne and ToMany (#240). This should work:
gradlew :data:testDebugUnitTest -x transformClassesWithObjectBoxAndroidTransformForDebug
(Note: this is because the output in build/intermediates/transforms is not used for unit tests, but the regular compile output in build/classes which only objectboxTransformDebugUnitTest writes to. Which adds an additional question mark on why the Android plugin runs the transform tasks in this case.)
-ut
Alright, pending review (internal transform-aar-unit-tests branch), changed the plugin to make the transformer check if entities and cursors are already modified. Then it will just warn about existing modifications instead of failing.
This should fix this issue by allowing the transformer to run on already transformed classes.
In addition the transformer will not touch existing code in Cursor#attachEntity and only amends its code if the __boxStore field is not already written. Otherwise, as said above, a warning will be written.
These changes also should fix #179 as they allow Jacoco to insert code that does not write the __boxStore field into the Cursor#attachEntity method.
-ut
Changes approved, this will be fixed with the next update. A workaround is available.
Please re-open if the next update does not fix this issue.
-ut
We just released version 2.2.0 with a fix. Please let us know if it is working for you. Thanks!
It's working, thanks! But I have encountered another error:
Not available in classpath: /native/libobjectbox-jni-linux-x64.so
File not available: /home/d/Documents/StudioProjects/temp/Sweetscounter/ui/libobjectbox-jni-linux-x64.so
java.lang.UnsatisfiedLinkError: no objectbox-jni in java.library.path
I get this message when running unit tests only.
Module data is using objectbox plugin (apply plugin: 'io.objectbox' in build.gradle). Tests there run fine.
Module ui does not implement objectbox plugin. But it depends on module data. Some tests there using a helper testing class from data containing MyObjectBox fail.
Using previous version those tests ran fine.
I solved this issue by copying file libobjectbox-jni-linux-x64.so from data module to ui module and tests ran fine.
@deividasstr Is that related to only 2.2?
Yes, I have just downgraded to 2.1 and tests ran fine (with -x transformClassesWithObjectBoxAndroidTransformForDebug)
Weird, not aware of changes here; @greenrobot-team maybe?
Would it make sense to have something like this in your build.gradle running the tests:
testImplementation "io.objectbox:objectbox-linux:$objectboxVersion"
testImplementation "io.objectbox:objectbox-macos:$objectboxVersion"
testImplementation "io.objectbox:objectbox-windows:$objectboxVersion"
PS.: could you double check that you are not using different versions in ui and data?
classpath "io.objectbox:objectbox-gradle-plugin:2.2.0" I am declaring this in the project-level build.gadle only.
testImplementation "io.objectbox:objectbox-linux:$objectboxVersion" generated the required file.
Anyway, to separate the concerns properly, the 'ui' should not be dependent on the database when there is a separate module for it. I just have to improve my 'ui' tests.
Thank you for quick response.
I tried to repro this by adding an AAR library module to a clean app, then adding ObjectBox to the library and calling a method that builds a BoxStore from a unit test in the library and one in the app:
aar-used-in-app-tests-gh-555.zip
Calling from the app unit test fails with the same error, regardless of using ObjectBox 2.1 or 2.2 or Android Gradle Plugin 3.1.4 or 3.2.0.
That is no surprise as the unit test dependencies (and test code itself) from the library module are not "forwarded" to the app. So I'm not sure how you got this working in the first place. Can you maybe update the example in that regard?
-ut
Sorry, it was my mistake.
After OS update there were issues with java which required java downgrade. I assume that because of those changes the file libobjectbox-jni-linux-x64.so was generated instead of the previous libobjectbox-linux-x64.so. Probably with the previous ObjectBox versions when I encountered this error in the UI module, I just copied this file from data module to ui without further thought.
And those files stayed, so when I downgraded to 2.1, everything worked.
I only use this base ObjectBox test from the data module in the ui module because I want to test Paging component in the ui, and the only way I found how to do this is by pre-creating test db which is passed to the ObjectBoxDataSource.
Sorry for the waste of time again.