We upgraded our Auth0 Android library from 1.30 to 2.0 and some of our unit tests that use OkHttp's MockWebServer
broke.
java.lang.ExceptionInInitializerError
which in turn is caused by java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.
java.lang.NoClassDefFoundError: Could not initialize class com.auth0.android.request.internal.DefaultThreadSwitcher
For context, we use RxJava3 and Android Jetpack libs such as LiveData in our code base, and Retrofit for REST API.
I tried adding
@ExtendWith(InstantExecutorExtension::class, RxImmediateScheduler::class)
in the class declaration like this:
@ExtendWith(InstantExecutorExtension::class, RxImmediateScheduler::class)
class AuthManagerTest {
But afterwards, all tests return with "Test ignored" in the logs:
Test ignored.
java.lang.InstantiationException
at sun.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:513)
at org.junit.platform.commons.util.ReflectionUtils.newInstance(ReflectionUtils.java:488)
at org.junit.jupiter.engine.extension.MutableExtensionRegistry.registerExtension(MutableExtensionRegistry.java:176)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.jupiter.engine.extension.MutableExtensionRegistry.createRegistryFrom(MutableExtensionRegistry.java:117)
at org.junit.jupiter.engine.descriptor.ExtensionUtils.populateNewExtensionRegistryFromExtendWithAnnotation(ExtensionUtils.java:77)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.prepare(ClassBasedTestDescriptor.java:143)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.prepare(ClassBasedTestDescriptor.java:78)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:111)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:111)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:79)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Here is a code snippet on how we initialize the test class:
class AuthManagerTest {
...
private lateinit var authManager: AuthManager
private lateinit var config: Auth0Config
private lateinit var server: MockWebServer
@MockK
private lateinit var context: Context
@MockK
private lateinit var credentialsManager: SecureCredentialsManager
...
...
@BeforeEach
fun setup() {
MockKAnnotations.init(this)
every { context.getSharedPreferences(any(), any()) } returns mockk()
every { credentialsManager.authToken } returns null
every { credentialsManager.userId } returns null
every { credentialsManager.refreshToken } returns null
every { credentialsManager.saveCredentials(any()) } just Runs
...
mockkObject(Credentials.Companion)
every { Credentials.fromAuth0Creds(any(), any()) } returns mockk()
server = MockWebServer().apply {
// we didn't use useHttps before but with the new version of Auth0 it seems https is mandatory
useHttps(testSslSocketFactory(), false)
start()
}
...
}
Here is the first test that fails:
@Test
fun `sendEmailCode returns EmailSent when response is successful`() {
server.enqueue(mockResponse(200, email_success_response))
val emailResult = authManager.sendEmailCode("me@example.org").blockingGet()
as EmailResult.EmailSent
assertEquals("me@example.org", emailResult.email)
assertNoToken()
}
Already fixed with version 2.3.0 of Auth0 android lib--see the README on how to solve this issue here