Eduard Boloș
11/25/2022, 5:27 PMEduard Boloș
11/25/2022, 5:27 PMandroid.util.Log.x
invocations in our tests that now fail. The error is the following:
java.lang.UnsatisfiedLinkError: 'int android.util.Log.println_native(int, int, java.lang.String, java.lang.String)'
at android.util.Log.println_native(Native Method)
at android.util.Log.d(Log.java:156)
It's worth nothing that we used to load our own android.util.Log
class in the test classpath and just call println()
in our implementation, but with that present and adding the paparazzi plugin, the screenshot tests don't even run, Gradle fails with the following:
JNIHelp F 11-25 18:20:30 <tel:880894843899|88089 4843899> java.lang.NoSuchMethodError: Method 'boolean android.util.Log.isLoggable(java.lang.String, int)' name or signature does not match
JNIHelp F 11-25 18:20:30 <tel:880894843899|88089 4843899> RegisterNatives failed for 'android/util/Log'; aborting...
So I commented out our android.util.Log
class.
The other error that comes up is:
Can't create handler inside thread Thread[Test worker,5,main] that has not called Looper.prepare()
java.lang.RuntimeException: Can't create handler inside thread Thread[Test worker,5,main] that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:227)
at android.os.Handler.<init>(Handler.java:129)
at android.os.CountDownTimer$1.<init>(CountDownTimer.java:129)
at android.os.CountDownTimer.<init>(CountDownTimer.java:129)
The first error I worked around by mocking Log
with mockk, and I guess I could do something similar for the second error, but I feel like I am just patching the symptoms of a bigger problem. Another solution I see is just to create a separate module only for the screenshot tests, but that's kind of annoying, since we have several modules xD.
Anyway, from what I could figure out, these issues arise because layoutlib
pulls in a reimplementation of the Android framework, and that conflicts somehow with our tests.
Not sure if this is something commonly encountered, but does anyone have some suggestions on how to best approach the above issues? 🙏Landry Norris
11/26/2022, 2:45 PMLogger.setWriters(CommonWriter())
Eduard Boloș
11/28/2022, 10:21 AMandroid.content.res.Resources#updateConfiguration(android.content.res.Configuration, android.util.DisplayMetrics)
, we had everything mocked in tests with MockK, but after adding Paparazzi the mocking doesn't work anymore, there are two errors we see:
java.lang.UnsatisfiedLinkError: 'int android.os.SystemProperties.native_get_int(java.lang.String, int)'
at android.os.SystemProperties.native_get_int(Native Method)
at android.os.SystemProperties.getInt(SystemProperties.java:180)
at android.util.DisplayMetrics.getDeviceDensity(DisplayMetrics.java:424)
at android.util.DisplayMetrics.<clinit>(DisplayMetrics.java:220)
at jdk.internal.reflect.GeneratedSerializationConstructorAccessor17.newInstance(Unknown Source)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at io.mockk.proxy.jvm.ObjenesisInstantiator.instanceViaObjenesis(ObjenesisInstantiator.kt:75)
at io.mockk.proxy.jvm.ObjenesisInstantiator.instantiateViaProxy(ObjenesisInstantiator.kt:66)
at io.mockk.proxy.jvm.ObjenesisInstantiator.instance(ObjenesisInstantiator.kt:29)
at io.mockk.impl.instantiation.JvmInstantiator$instantiate$2.invoke(JvmInstantiator.kt:16)
at io.mockk.impl.instantiation.AbstractInstantiator.instantiateViaInstanceFactoryRegistry(AbstractInstantiator.kt:17)
at io.mockk.impl.instantiation.JvmInstantiator.instantiate(JvmInstantiator.kt:15)
at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1$1.invoke(RecordingState.kt:49)
at io.mockk.impl.instantiation.JvmAnyValueGenerator$anyValue$2.invoke(JvmAnyValueGenerator.kt:35)
at io.mockk.impl.instantiation.AnyValueGenerator.anyValue(AnyValueGenerator.kt:34)
at io.mockk.impl.instantiation.JvmAnyValueGenerator.anyValue(JvmAnyValueGenerator.kt:31)
at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1.invoke(RecordingState.kt:48)
at io.mockk.impl.recording.JvmSignatureValueGenerator.signatureValue(JvmSignatureValueGenerator.kt:20)
at io.mockk.impl.recording.states.RecordingState.matcher(RecordingState.kt:47)
at io.mockk.impl.recording.CommonCallRecorder.matcher(CommonCallRecorder.kt:52)
at AppTest$fakeApp$1$getResources$1$3.invoke(AppTest.kt:73)
at AppTest$fakeApp$1$getResources$1$3.invoke(AppTest.kt:43)
at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:25)
at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:78)
at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:40)
at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalEvery(API.kt:93)
at io.mockk.MockKKt.every(MockK.kt:98)
at AppTest$fakeApp$1.getResources(AppTest.kt:43)
and
java.lang.NoClassDefFoundError: Could not initialize class android.util.DisplayMetrics
at jdk.internal.reflect.GeneratedSerializationConstructorAccessor17.newInstance(Unknown Source)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
at org.objenesis.instantiator.sun.SunReflectionFactoryInstantiator.newInstance(SunReflectionFactoryInstantiator.java:48)
at io.mockk.proxy.jvm.ObjenesisInstantiator.instanceViaObjenesis(ObjenesisInstantiator.kt:75)
at io.mockk.proxy.jvm.ObjenesisInstantiator.instantiateViaProxy(ObjenesisInstantiator.kt:66)
at io.mockk.proxy.jvm.ObjenesisInstantiator.instance(ObjenesisInstantiator.kt:29)
at io.mockk.impl.instantiation.JvmInstantiator$instantiate$2.invoke(JvmInstantiator.kt:16)
at io.mockk.impl.instantiation.AbstractInstantiator.instantiateViaInstanceFactoryRegistry(AbstractInstantiator.kt:17)
at io.mockk.impl.instantiation.JvmInstantiator.instantiate(JvmInstantiator.kt:15)
at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1$1.invoke(RecordingState.kt:49)
at io.mockk.impl.instantiation.JvmAnyValueGenerator$anyValue$2.invoke(JvmAnyValueGenerator.kt:35)
at io.mockk.impl.instantiation.AnyValueGenerator.anyValue(AnyValueGenerator.kt:34)
at io.mockk.impl.instantiation.JvmAnyValueGenerator.anyValue(JvmAnyValueGenerator.kt:31)
at io.mockk.impl.recording.states.RecordingState$matcher$signatureValue$1.invoke(RecordingState.kt:48)
at io.mockk.impl.recording.JvmSignatureValueGenerator.signatureValue(JvmSignatureValueGenerator.kt:20)
at io.mockk.impl.recording.states.RecordingState.matcher(RecordingState.kt:47)
at io.mockk.impl.recording.CommonCallRecorder.matcher(CommonCallRecorder.kt:52)
at AppTest$fakeApp$1$getResources$1$3.invoke(AppTest.kt:73)
at AppTest$fakeApp$1$getResources$1$3.invoke(AppTest.kt:43)
at io.mockk.impl.eval.RecordedBlockEvaluator$record$block$1.invoke(RecordedBlockEvaluator.kt:25)
at io.mockk.impl.eval.RecordedBlockEvaluator$enhanceWithRethrow$1.invoke(RecordedBlockEvaluator.kt:78)
at io.mockk.impl.recording.JvmAutoHinter.autoHint(JvmAutoHinter.kt:23)
at io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:40)
at io.mockk.impl.eval.EveryBlockEvaluator.every(EveryBlockEvaluator.kt:30)
at io.mockk.MockKDsl.internalEvery(API.kt:93)
at io.mockk.MockKKt.every(MockK.kt:98)
at AppTest$fakeApp$1.getResources(AppTest.kt:43)
Needless to say, I didn't manage to find a workaround this time 😞Jan Skrasek
06/01/2023, 3:10 PMEduard Boloș
06/02/2023, 10:42 AMJan Skrasek
06/02/2023, 10:43 AM