在Ok188bet金宝搏官网Cupid,我们经常使用的Mockito库创建我们依赖嘲笑我们的JUnit测试中使用。这让我们对某些方法轻松模拟返回值,或验证的方法被称为我们的一个依赖,但它可以测试下提供并发症组件之间的集成和它的依赖变得更加复杂。

在这篇文章中,我们正在经历的限制走路用嘲讽库中找到,并讨论我们如何能够利用我们自己的假执行闯过这个限制。让我们通过设置阶段为这个问题开始。

设置阶段

在我们讨论这个问题,让我们确保我们理解试验下的部件。我们将寻找一个视图模型,负责制作的网络请求,并呈现出一些结果。

下面是视图模型的片断,但如果你想看到相关的类,你可以找到他们在这个要点。注意,在这个视图模型,只要它的创建,我们要求里面的个人资料信息在里面方法:

类ProfileViewModel(用户ID:字符串;存储库:ProfileRepository,backgroundScheduler:调度= Schedulers.io(),mainScheduler:调度= AndroidSchedulers.mainThread()):视图模型(){私人188博金宝电子体育频道VAL _STATE = MutableLiveData ()VAL状态:LiveData = _STATE INIT {_state.value = ProfileViewState.loading()存储库.fetchProfile(用户id).subscribeOn(backgroundScheduler).observeOn(mainScheduler).subscribe({用户 - > _state.value = ProfileViewState.success(用户)}{错误 - > _state.value = ProfileViewState.error(误差)})}}

一旦被创建我们的视图模型,我们将发出加载状态下我们LiveData。然后,我们将要求一个配置文件,如果调用成功或失败后一个新ProfileViewState。

这是我们在测试需要为我们的组件的一切。接下来我们可以测试它。

测试中的视图模型

我们会以一个积极的情况下,测试开始,以确保当我们请求用户,在加载状态下发出之后的数据状态。让我们来看看该测试的样子:

类ProfileViewModelTest {@Test乐趣loadProfile(){VAL为testUser =用户(用户ID = “123”)VAL mockRepository = Mockito.mock(ProfileRepository :: class.java)每当(mockRepository.fetchProfile(anyString())).thenReturn(单。just(testUser)) val viewModel = ProfileViewModel( userId = "123", repository = mockRepository, backgroundScheduler = Schedulers.trampoline(), mainScheduler = Schedulers.trampoline() ) val observedStates = viewModel.state.testObserver().observedValues assertThat(observedStates.size).isEqualTo(2) val firstState = observedStates[0] val secondState = observedStates[1] assertThat(firstState.loading).isTrue() assertThat(secondState.data).isEqualTo(testUser) } }

如果你想看到的实施.testObserver()你可以找到它在这个要点

测试失败

令我们惊讶的是,本次测试将失败!我们嘲笑一个成功的数据请求,因此我们预计,我们的observedStates有两个项目:一个用于装载状态,一个是成功的数据状态。在运行测试,第一个断言失败。我们的测试表示,observedStates.size是一个,并且该值是数据的状态。

换句话说,我们的测试无法确认发生装载状态。

发生了什么?

让我们来想想什么是我们单位不是真正的测试代码不同。在我们的单元测试,我们传递Scheduler.trampoline()从RxJava这有助于使网络运行的要求就好像它是连续的。在这个测试而言,就好像一旦创建视图模型的网络请求立即成功。

然后,创建视图模型我们后,我们应用测试观察者在ViewModel.stateLiveData,这已经在加载数据状态。这意味着加载状态发生得早的时间 - 真实创建之前,我们不能观察LiveData,所以我们没有办法来验证加载状态想过。

这种并发症是由我们的嘲弄库,它告诉我们的模拟库返回信息马上引起的。取而代之的是,我们可以创建一个ProfileRepository我们自己伪造的实现,我们在拥有完全控制权,并可以控制数据的发射,以确保我们的单元测试捕获加载状态。

创建一个假的

要创建一个假的实现中,我们通过创建一个新的类,它实现我们的接口开始。请记住,我们不希望我们的假返回数据向右走,因为这只会导致同样的问题。相反,因为我们使用的RxJava,我们可以实现在使用的方式我们假BehaviorSubject在幕后,我们可以控制的。

类FakeRepository:ProfileRepository {私人VAL userSubject:BehaviorSubject <用户> = BehaviorSubject.create()重写乐趣fetchProfile(用户ID:字符串):单<用户> {返回userSubject.hide()firstOrError()}}

如果您使用的协同程序,你在这里使用的实施可能会改变,但概念是相同的:我们不希望从返回fetchProfile()随着信息的时候了。我们要确保我们的假货实现精确控制,当这些数据被发射。

控制排放数据

由于我们的假货实现使用BehaviorSubject作为底层数据源,我们可以创建自己的公共方法发出到它时,我们喜欢:

类FakeRepository:ProfileRepository {// ...乐趣emitUser(用户:用户){this.userSubject.onNext(用户)}}

更新测试,以验证加载状态

现在,我们已经在地方,我们已经细粒度控制。当数据从我们的仓库发出了一个系统,我们可以利用这个来准确地测试我们的负荷状态。我们将按照这个食谱:

  1. 创建我们的假货仓库和视图模型组件
  2. 由于我们的假货不发射数据马上,我们将能够验证我们在加载状态。
  3. 我们可以控制假执行发射数据。
  4. 最后,我们可以验证我们的视图模型现在处于加载数据状态。
类ProfileViewModelTest {@Test乐趣loadProfile(){VAL为testUser =用户(用户ID = “123”)//使用的是假的,而不是VAL的Mockito = fakeRepository FakeRepository()//创建我们的视图模型视图模型VAL = ProfileViewModel(用户ID = “123”,库= fakeRepository,backgroundScheduler = Schedulers.trampoline(),mainScheduler = Schedulers.trampoline())VAL testObserver = viewModel.state.testObserver()VAL observedStates = testObserver.observedValues //验证我们只有负荷状态assertThat(observedStates.size).isEqualTo(1)VAL firstState = observedStates [0] assertThat(firstState.loading).isTrue()//的Emit数据,验证我们进入一个//加载的数据的状态fakeRepository.emitUser(为testUser)assertThat(observedStates.size).isEqualTo(2)VAL secondState = observedStates [1] assertThat(secondState.data).isEqualTo(为testUser)}}

概括

惩戒库提供了在我们的Android单元测试创​​建依赖于使用一个快速的解决方案,但在来具有控制这些依赖的行为限制的代价。188博金宝电子体育频道通过利用接口及我们的存在于我们的代码库自己的假执行,我们有过的依赖完全控制,我们可以用它来进行无流量数据的排放控制,彻底单元测试我们的组件。

我希望你发现这是很有帮助!如果你使用的是假对一个模拟的其他例子,让我知道推特

在OkCupid的工作感兴趣吗?188bet金宝搏官网我们正在招聘