涉及 MockWebServer 的单元测试因 Auth0 的 Android 库版本 2 而失败
Unit tests involving MockWebServer fails with Auth0's Android library version 2
我们将 Auth0 Android 库从 1.30 升级到 2.0,我们的一些使用 OkHttp MockWebServer
的单元测试失败了。
- 第一个测试失败并显示
java.lang.ExceptionInInitializerError
,这又是由 java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.
引起的
- 接下来的三个测试失败
java.lang.NoClassDefFoundError: Could not initialize class com.auth0.android.request.internal.DefaultThreadSwitcher
- 其余的测试会一直卡住,直到被取消。
对于上下文,我们在我们的代码库中使用 RxJava3 和 Android Jetpack 库,例如 LiveData,以及 Retrofit for REST API.
我试过添加
@ExtendWith(InstantExecutorExtension::class, RxImmediateScheduler::class)
在 class 声明中是这样的:
@ExtendWith(InstantExecutorExtension::class, RxImmediateScheduler::class)
class AuthManagerTest {
但之后,所有测试 return 在日志中显示“忽略测试”:
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(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(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(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(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[=12=](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)
这是我们如何初始化测试的代码片段 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()
}
...
}
这是第一个失败的测试:
@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()
}
已通过 Auth0 android lib 的 2.3.0 版修复——请参阅有关如何解决此问题的自述文件 here
我们将 Auth0 Android 库从 1.30 升级到 2.0,我们的一些使用 OkHttp MockWebServer
的单元测试失败了。
- 第一个测试失败并显示
java.lang.ExceptionInInitializerError
,这又是由java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.
引起的
- 接下来的三个测试失败
java.lang.NoClassDefFoundError: Could not initialize class com.auth0.android.request.internal.DefaultThreadSwitcher
- 其余的测试会一直卡住,直到被取消。
对于上下文,我们在我们的代码库中使用 RxJava3 和 Android Jetpack 库,例如 LiveData,以及 Retrofit for REST API.
我试过添加
@ExtendWith(InstantExecutorExtension::class, RxImmediateScheduler::class)
在 class 声明中是这样的:
@ExtendWith(InstantExecutorExtension::class, RxImmediateScheduler::class)
class AuthManagerTest {
但之后,所有测试 return 在日志中显示“忽略测试”:
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(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(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(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(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[=12=](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)
这是我们如何初始化测试的代码片段 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()
}
...
}
这是第一个失败的测试:
@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()
}
已通过 Auth0 android lib 的 2.3.0 版修复——请参阅有关如何解决此问题的自述文件 here