SPEK 改造API测试崩溃



我正在尝试使用Spek

测试Raterofit API

它在{...} block> block

on 上抛出nullpointerexception

关联的stacktrace:https://pastebin.com/gy6dltgg

这是我的测试类

@RunWith(JUnitPlatform::class)
class AccountCheckViewModelTest : Spek({
    include(RxSchedulersOverrideRule)
    val httpException = mock<HttpException> {
        on { code() }.thenReturn(400)
    }
    given(" account check view model") {
        var accountCheckRequest = mock<CheckExistingAccountRequest>()
        var accountCheckResponse = mock<CheckExistingAccountResponse>()
        var webService = mock<IAPICalls>()
        val accountCheckViewModel = spy(VMAccountCheck(webService))
        beforeEachTest {
            accountCheckRequest = mock<CheckExistingAccountRequest>() {
                on { email }.thenReturn("foo@mail")
            }
            accountCheckResponse = mock<CheckExistingAccountResponse>() {
                on { firstName }.thenReturn("foo")
                on { email }.thenReturn("foo@mail")
            }
            webService = mock<IAPICalls> {
                on { checkExistingAccount(accountCheckRequest) }.thenReturn(Flowable.just(accountCheckResponse))
            }
         }
        on("api success") {
            accountCheckViewModel.checkIfAccountExists(request = accountCheckRequest)
            it("should call live data with first name as foo") {
               verify(accountCheckViewModel, times(1)).updateLiveData(accountCheckResponse.firstName, accountCheckResponse.email, null)
            }
        }
    }
}

这是我的rxschedulersoverridespek类

 class RxSchedulersOverrideSpek : Spek({
    beforeGroup {
        RxJavaPlugins.onIoScheduler(Schedulers.trampoline())
        RxJavaPlugins.onComputationScheduler(Schedulers.trampoline())
        RxJavaPlugins.onNewThreadScheduler(Schedulers.trampoline())
    }
})

您应该使用memoized正确设置测试值。问题是accountCheckViewModel是在Spek的发现阶段初始化的,而传递给accountCheckViewModelwebService模拟是该点的值(您没有模拟其任何方法(。beforeEachTest是在执行阶段运行的,您已将webService重新分配给适当的模拟,但accountCheckViewModel仍然保留上一个值。

given(" account check view model") {
  val accountCheckRequest by memoized {
    mock<CheckExistingAccountRequest>() {
      on { email }.thenReturn("foo@mail")
    }
  }
  val accountCheckResponse by memoized {
    mock<CheckExistingAccountResponse>() {
      on { firstName }.thenReturn("foo")
      on { email }.thenReturn("foo@mail")
    }
  }
  val webService by memoized {
    mock<IAPICalls> {
      on { checkExistingAccount(accountCheckRequest) }.thenReturn(Flowable.just(accountCheckResponse))
    }
  }
  val accountCheckViewModel by memoized {
    spy(VMAccountCheck(webService))
  }
  on("api success") {
    accountCheckViewModel.checkIfAccountExists(request = accountCheckRequest)
    it("should call live data with first name as foo") {
      verify(accountCheckViewModel, times(1)).updateLiveData(accountCheckResponse.firstName, accountCheckResponse.email, null)
    }
  }
}

假设您使用 rxjava2 带有 rxandroid 您应该用Schedulers.trampoline()覆盖Rxandroid调度程序。这样,所有在蹦床((上订阅的作业都将在同一线程中排队和一个一个。

RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }

您的RxSchedulersOverrideSpek.kt应该看起来像这样:

object RxSchedulersOverrideSpek : Spek({
    beforeGroup {
        RxJavaPlugins.onIoScheduler(Schedulers.trampoline())
        RxJavaPlugins.onComputationScheduler(Schedulers.trampoline())
        RxJavaPlugins.onNewThreadScheduler(Schedulers.trampoline())
        RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }
    }
    afterGroup {
        RxJavaPlugins.reset()
        RxAndroidPlugins.reset()
    }
})

最新更新