问题描述
我是 MockK (https://mockk.io) 的新手,我正在尝试使用 MockK 在 Instrumented Test [mockk-android Version: 1.11.0](androidTest 文件夹)中测试 Android Worker。
我正在 Kotlin 中测试 Worker 实现,如下所述:https://developer.android.com/topic/libraries/architecture/workmanager/how-to/testing-worker-impl#kotlin
TL;DR:
我试图做的是监视 MyWorker。它应该像往常一样,只有私有的 Worker 函数 MyWorker.sendXmlFile(file: File?) 应该被模拟为返回 true,因为比 Worker(见代码)返回 Result.success()。正确的做法是什么?
这是要测试的 Worker:
class `MyWorker(context: Context,workerParams: WorkerParameters) : Worker(context,workerParams) {
companion object {
/** If the file upload fails the worker retries (Result.retry()) to upload until the upload was successful (Result.success()) or [MAX_RETRIES] is reached (Result.failure())*/
private var MAX_RETRIES : Int = 10
private var sharedPref : SharedPreferences? = null
private var ftpEndpoint : String? = null
private var ftpClient : FTPClient? = null
private var ftpUserName : String? = null
private var ftpPassword : String? = null
private var ftpStatusDirectory : String? = "";
}
override fun doWork(): Result {
val xmlOutput = MyObserver.getXmlOutput()
if(xmlOutput.isNotEmpty()) {
if(sendXmlFile(createXmlFile(xmlOutput)) {
//[...]
return Result.success()
} else {
//FileUpload was not successful
if (runAttemptCount > MAX_RETRIES) {
Timber.d("{doWork()} retried %d times,max retries reached: failure",runAttemptCount)
return Result.failure()
}
Timber.d("{doWork()} retried %d times: try again",runAttemptCount)
return Result.retry()
}
}
return Result.failure()
}
private fun createXmlFile(xmlString : String): File {
[...]
}
/**
* Uploads a local file to the FTP server and deletes the local file afterwards
*/
private fun sendXmlFile(file: File?) : Boolean {
var result : Boolean = false;
if (file?.exists() == true) {
if(getFtpConnection@R_996_4045@ion() && connectFTP()) {
result = FtpConnectionManager.uploadFiletoFTP(ftpClient,file)
}
//remove file after upload
file.deleteOnExit()
}
return result
}
}
这是我的 androidTest 文件:
@RunWith(AndroidJUnit4ClassRunner::class)
class MyWorkerTest {
private lateinit var context: Context
private lateinit var executor: Executor
@Before
fun setUp() {
context = ApplicationProvider.getApplicationContext()
executor = Executors.newSingleThreadExecutor()
}
@Test
fun test() {
var worker = TestWorkerBuilder<MyWorker>(
context = context,executor = executor
).build()
assertthat("xmlOutput is empty in the beginning",MyObserver.getXmlOutput().isNotEmpty(),`is`(false))
var result = worker.doWork()
assertthat("Because xmlOutput is empty worker should fail",result,`is`(ListenableWorker.Result.failure()))
mockkObject(MyObserver.Companion)
val xmlString = "<data>test</data>"
every { MyObserver.Companion.getXmlOutput() } returns xmlString
assertthat("MyObserver.getXmlOutput should be $xmlString Now",MyObserver.Companion.getXmlOutput().equals(xmlString))
assertthat("MyObserver.getXmlOutput is not empty Now ",MyObserver.getXmlOutput().isNotEmpty())
//this is what is not working:
val myWorker = spyk(TestWorkerBuilder<MyWorker>(
context = context,executor = executor
).build(),recordPrivateCalls = true)
every { myWorker["createXmlFile"](any()) } returns true
result = myWorker.doWork()
assertthat("worker will be successful Now",`is`(ListenableWorker.Result.success()))
//unmock everything
unmockkAll()
}
}
这是我得到的错误:
java.lang.Arrayindexoutofboundsexception: length=0; index=0
at kotlin.reflect.jvm.internal.impl.descriptors.runtime.structure.ReflectJavaMember.getValueParameters(ReflectJavaMember.kt:59)
at kotlin.reflect.jvm.internal.impl.descriptors.runtime.structure.ReflectJavaMethod.getValueParameters(ReflectJavaMethod.kt:26)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.resolveMethodToFunctionDescriptor(LazyJavaScope.kt:153)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$declaredFunctions$1.invoke(LazyJavaScope.kt:94)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$declaredFunctions$1.invoke(LazyJavaScope.kt:59)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:512)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:587)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$declaredFunctions$1.invoke(LazyJavaScope.kt:89)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$declaredFunctions$1.invoke(LazyJavaScope.kt:59)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:512)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:587)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:117)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:59)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:512)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:587)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.getContributedFunctions(LazyJavaScope.kt:267)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.getContributedFunctions(LazyJavaClassMemberScope.kt:747)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.getFunctionsFromSupertypes(LazyJavaClassMemberScope.kt:438)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.computeNonDeclaredFunctions(LazyJavaClassMemberScope.kt:268)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:121)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope$functions$1.invoke(LazyJavaScope.kt:59)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:512)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:587)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaScope.getContributedFunctions(LazyJavaScope.kt:267)
at kotlin.reflect.jvm.internal.impl.load.java.lazy.descriptors.LazyJavaClassMemberScope.getContributedFunctions(LazyJavaClassMemberScope.kt:747)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.computeNonDeclaredFunctions(DeserializedClassDescriptor.kt:242)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.computeFunctions(DeserializedMemberScope.kt:102)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.access$computeFunctions(DeserializedMemberScope.kt:40)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$functions$1.invoke(DeserializedMemberScope.kt:66)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope$functions$1.invoke(DeserializedMemberScope.kt:40)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunction.invoke(LockBasedStorageManager.java:512)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$MapBasedMemoizedFunctionToNotNull.invoke(LockBasedStorageManager.java:587)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.getContributedFunctions(DeserializedMemberScope.kt:139)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getContributedFunctions(DeserializedClassDescriptor.kt:231)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.addFunctionsAndProperties(DeserializedMemberScope.kt:221)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedMemberScope.computeDescriptors(DeserializedMemberScope.kt:181)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(DeserializedClassDescriptor.kt:217)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope$allDescriptors$1.invoke(DeserializedClassDescriptor.kt:210)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasedLazyValue.invoke(LockBasedStorageManager.java:355)
at kotlin.reflect.jvm.internal.impl.storage.LockBasedStorageManager$LockBasednotNullLazyValue.invoke(LockBasedStorageManager.java:474)
at kotlin.reflect.jvm.internal.impl.serialization.deserialization.descriptors.DeserializedClassDescriptor$DeserializedClassMemberScope.getContributedDescriptors(DeserializedClassDescriptor.kt:227)
at kotlin.reflect.jvm.internal.impl.resolve.scopes.ResolutionScope$DefaultImpls.getContributedDescriptors$default(ResolutionScope.kt:52)
at kotlin.reflect.jvm.internal.KDeclarationContainerImpl.getMembers(KDeclarationContainerImpl.kt:65)
at kotlin.reflect.jvm.internal.KClassImpl$Data$declarednonStaticmembers$2.invoke(KClassImpl.kt:159)
at kotlin.reflect.jvm.internal.KClassImpl$Data$declarednonStaticmembers$2.invoke(KClassImpl.kt:44)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getDeclarednonStaticmembers(UnkNown Source:8)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticmembers$2.invoke(KClassImpl.kt:168)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allNonStaticmembers$2.invoke(KClassImpl.kt:44)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllNonStaticmembers(UnkNown Source:8)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:174)
at kotlin.reflect.jvm.internal.KClassImpl$Data$allMembers$2.invoke(KClassImpl.kt:44)
at kotlin.reflect.jvm.internal.ReflectProperties$LazySoftVal.invoke(ReflectProperties.java:92)
at kotlin.reflect.jvm.internal.ReflectProperties$Val.getValue(ReflectProperties.java:31)
at kotlin.reflect.jvm.internal.KClassImpl$Data.getAllMembers(UnkNown Source:8)
at kotlin.reflect.jvm.internal.KClassImpl.getMembers(KClassImpl.kt:192)
at kotlin.reflect.full.KClasses.getFunctions(KClasses.kt:90)
at io.mockk.InternalPlatformdsl.dynamicCall(InternalPlatformdsl.kt:99)
at io.mockk.MockKMatcherScope$DynamicCall.invoke(API.kt:1980)
at com.umlaut.thc.tnaappdesign.MyWorkerTest$test$2.invoke(MyWorkerTest.kt:98)
at com.example.MyWorkerTest$test$2.invoke(MyWorkerTest.kt:29)
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:92)
at io.mockk.MockKKt.every(MockK.kt:98)
at com.example.MyWorkerTest.test(MyWorkerTest.kt:89)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runchild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runchild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runchildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runners.Suite.runchild(Suite.java:128)
at org.junit.runners.Suite.runchild(Suite.java:27)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runchildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:395)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2238)
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)