android - 注入假改造服务以在 AndroidTest 中使用
问题描述
我有一个对象 EventLogger,用于存储和转发事件,它有一个可注入的改造 api:
object EventLogger {
...
private var apiInstance: EventLoggingService? = null
/**
* Inject the api provider
*/
fun setApi(eventLoggingService: EventLoggingService?) {
Log.d(TAG, "Api set")
apiInstance = eventLoggingService
}
/**
* Get the injected api
*/
fun getApi(): EventLoggingService? = apiInstance
fun send() {
// eventsToSend will be populated into local var from database
getApi()?.logEvents(EventLoggingRequest(eventsToSend))?.retry(getRetryCount())
?.subscribeOn(Schedulers.io())
?.onErrorComplete()
?.subscribe({ onSuccessfulSync(eventsToSend, devicesToSend, commentsToSend) }, { Log.d(TAG, "error on sending ${eventsToSend.size} events")})
}
fun onSuccessfulSync(eventsToSend: List<LoggedEvent>) {
// remove synced events from database
}
将被伪造的改造服务:
interface EventLoggingService {
@POST("v1/system/events")
fun logEvents(
@Body eventLoggingRequest: EventLoggingRequest
): Single<String>
}
在我的 AndroidTest 中:
@RunWith(AndroidJUnit4::class)
class EventLoggerAndroidTest {
...
@Test
fun testSend() {
// populate fake events
EventLogger.setApi(SucceedingEventService())
EventLogger.send()
// assert events removed from database
}
class FailingEventService : EventLoggingService {
override fun logEvents(eventLoggingRequest: EventLoggingRequest): Single<String> {
println("${eventLoggingRequest.events.size} events sent to failing service")
return Single.error(TimeoutException())
}
}
class SucceedingEventService : EventLoggingService {
override fun logEvents(eventLoggingRequest: EventLoggingRequest): Single<String> {
println("${eventLoggingRequest.events.size} events sent to succeeding service")
return Single.create {
it.onSuccess("")
}
}
}
由于断言错误和此堆栈跟踪,此测试失败:
I/System.out: 2 events sent to succeeding service
E/TestRunner: failed: pageData(com.doctella.doc.events.EventLoggerAndroidTest)
----- begin exception -----
W/System.err: io.reactivex.rxjava3.exceptions.CompositeException: 2 exceptions occurred.
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybeCallbackObserver.onError(MaybeCallbackObserver.java:85)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybePeek$MaybePeekObserver.onErrorInner(MaybePeek.java:147)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybePeek$MaybePeekObserver.onSuccess(MaybePeek.java:117)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybeOnErrorComplete$OnErrorCompleteMultiObserver.onSuccess(MaybeOnErrorComplete.java:68)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onSuccess(SingleSubscribeOn.java:68)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableSingleSingle$SingleElementSubscriber.onComplete(FlowableSingleSingle.java:114)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate$RetrySubscriber.onComplete(FlowableRetryPredicate.java:104)
W/System.err: at io.reactivex.rxjava3.internal.subscriptions.DeferredScalarSubscription.complete(DeferredScalarSubscription.java:135)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable$SingleToFlowableObserver.onSuccess(SingleToFlowable.java:62)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleCreate$Emitter.onSuccess(SingleCreate.java:68)
E/TestRunner: java.lang.AssertionError: expected:<1> but was:<3>
at org.junit.Assert.fail(Assert.java:89)
at org.junit.Assert.failNotEquals(Assert.java:835)
at org.junit.Assert.assertEquals(Assert.java:120)
at org.junit.Assert.assertEquals(Assert.java:146)
at com.doctella.doc.events.EventLoggerAndroidTest$pageData$$inlined$use$lambda$1.execute(EventLoggerAndroidTest.kt:328)
at io.realm.Realm.executeTransaction(Realm.java:1537)
at com.doctella.doc.events.EventLoggerAndroidTest.pageData(EventLoggerAndroidTest.kt:323)
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 androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
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 androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:154)
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:2209)
E/TestRunner: ----- end exception -----
W/System.err: at com.doctella.doc.events.EventLoggerAndroidTest$SucceedingEventService$logEvents$1.subscribe(EventLoggerAndroidTest.kt:416)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:40)
at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15696)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate$RetrySubscriber.subscribeNext(FlowableRetryPredicate.java:124)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate.subscribeActual(FlowableRetryPredicate.java:42)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableSingleSingle.subscribeActual(FlowableSingleSingle.java:39)
W/System.err: at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
W/System.err: at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:614)
W/System.err: at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
W/System.err: at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W/System.err: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
W/System.err: ComposedException 1 :
io.mockk.MockKException: can't find stub EventLogger(object EventLogger)
W/System.err: at io.mockk.impl.stub.StubRepository.stubFor(StubRepository.kt:16)
at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:13)
W/System.err: at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
W/System.err: at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:263)
at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:25)
W/System.err: at io.mockk.proxy.android.advice.Advice$handle$1.call(Advice.kt:77)
W/System.err: at com.doctella.doc.events.EventLogger.getTAG(Unknown Source:33)
at com.doctella.doc.events.EventLogger$send$2.accept(EventLogger.kt:185)
W/System.err: at com.doctella.doc.events.EventLogger$send$2.accept(EventLogger.kt:15)
at io.reactivex.rxjava3.internal.operators.maybe.MaybePeek$MaybePeekObserver.onSuccess(MaybePeek.java:114)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybeOnErrorComplete$OnErrorCompleteMultiObserver.onSuccess(MaybeOnErrorComplete.java:68)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onSuccess(SingleSubscribeOn.java:68)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableSingleSingle$SingleElementSubscriber.onComplete(FlowableSingleSingle.java:114)
I/TestRunner: finished: pageData(com.doctella.doc.events.EventLoggerAndroidTest)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate$RetrySubscriber.onComplete(FlowableRetryPredicate.java:104)
W/System.err: at io.reactivex.rxjava3.internal.subscriptions.DeferredScalarSubscription.complete(DeferredScalarSubscription.java:135)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable$SingleToFlowableObserver.onSuccess(SingleToFlowable.java:62)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleCreate$Emitter.onSuccess(SingleCreate.java:68)
W/System.err: at com.doctella.doc.events.EventLoggerAndroidTest$SucceedingEventService$logEvents$1.subscribe(EventLoggerAndroidTest.kt:416)
at io.reactivex.rxjava3.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:40)
W/System.err: at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37)
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15696)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate$RetrySubscriber.subscribeNext(FlowableRetryPredicate.java:124)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate.subscribeActual(FlowableRetryPredicate.java:42)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableSingleSingle.subscribeActual(FlowableSingleSingle.java:39)
W/System.err: at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:614)
W/System.err: at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
W/System.err: at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
W/System.err: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/System.err: at java.lang.Thread.run(Thread.java:919)
ComposedException 2 :
io.mockk.MockKException: can't find stub EventLogger(object EventLogger)
W/System.err: at io.mockk.impl.stub.StubRepository.stubFor(StubRepository.kt:16)
at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:13)
W/System.err: at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:263)
W/System.err: at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:25)
W/System.err: at io.mockk.proxy.android.advice.Advice$handle$1.call(Advice.kt:77)
at com.doctella.doc.events.EventLogger.getTAG(EventLogger.kt:16)
at com.doctella.doc.events.EventLogger$send$4.accept(EventLogger.kt:188)
W/System.err: at com.doctella.doc.events.EventLogger$send$4.accept(EventLogger.kt:15)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybeCallbackObserver.onError(MaybeCallbackObserver.java:82)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybePeek$MaybePeekObserver.onErrorInner(MaybePeek.java:147)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybePeek$MaybePeekObserver.onSuccess(MaybePeek.java:117)
W/System.err: at io.reactivex.rxjava3.internal.operators.maybe.MaybeOnErrorComplete$OnErrorCompleteMultiObserver.onSuccess(MaybeOnErrorComplete.java:68)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onSuccess(SingleSubscribeOn.java:68)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableSingleSingle$SingleElementSubscriber.onComplete(FlowableSingleSingle.java:114)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate$RetrySubscriber.onComplete(FlowableRetryPredicate.java:104)
W/System.err: at io.reactivex.rxjava3.internal.subscriptions.DeferredScalarSubscription.complete(DeferredScalarSubscription.java:135)
at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable$SingleToFlowableObserver.onSuccess(SingleToFlowable.java:62)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleCreate$Emitter.onSuccess(SingleCreate.java:68)
W/System.err: at com.doctella.doc.events.EventLoggerAndroidTest$SucceedingEventService$logEvents$1.subscribe(EventLoggerAndroidTest.kt:416)
W/System.err: at io.reactivex.rxjava3.internal.operators.single.SingleCreate.subscribeActual(SingleCreate.java:40)
W/System.err: at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
at io.reactivex.rxjava3.internal.operators.single.SingleToFlowable.subscribeActual(SingleToFlowable.java:37)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15696)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate$RetrySubscriber.subscribeNext(FlowableRetryPredicate.java:124)
at io.reactivex.rxjava3.internal.operators.flowable.FlowableRetryPredicate.subscribeActual(FlowableRetryPredicate.java:42)
W/System.err: at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750)
W/System.err: at io.reactivex.rxjava3.internal.operators.flowable.FlowableSingleSingle.subscribeActual(FlowableSingleSingle.java:39)
W/System.err: at io.reactivex.rxjava3.core.Single.subscribe(Single.java:4813)
at io.reactivex.rxjava3.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89)
W/System.err: at io.reactivex.rxjava3.core.Scheduler$DisposeTask.run(Scheduler.java:614)
W/System.err: at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:65)
W/System.err: at io.reactivex.rxjava3.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:56)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err: at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
解决方案
推荐阅读
- javascript - 我正在尝试使用 Javascript 更改 CSS 元素,但它不起作用
- c# - 如果在 IIS 中作为虚拟目录运行,.net 核心应用程序错误 502.5
- aggregation - Clean Architecture中的单一职责原则,将UseCases聚合在一个UseCaseManager中,该UseCaseManager可以提供基于In & Out Object的UseCase。
- php - Mysql 在 xampp 上意外停止
- php - 声明有效但不会重定向?
- java - Spring Boot 和 Ajax 中的自动上传功能
- javascript - 过滤特定元素并单击相应按钮
- javascript - 如何使用 jquery 切换具有垂直文本和内容的垂直选项卡
- asp.net-core - NuGet.targets 错误:'.',十六进制值 0x00,升级到 .Net Core 2.1.1 后是无效字符
- javascript - 在我的数组显示中删除 NaN