所以我有了存储库,它为客户端提供了Observable。有没有办法可以模拟这个存储库,所以我不需要从我的模拟器发送位置或使用真实设备获取一些位置?
以下是界面的外观:
loops
在我的客户端,我使用这样:
interface RxLocationRepository {
@SuppressLint("MissingPermission")
fun onLocationUpdate(): Observable<Location>
fun stopLocationUpdates()
}
所以我将这个获得的位置发送到我的appendGeoEvent方法。
我可以使用例如Mockito,但我不知道如何模拟这个存储库,所以我可以使用假位置。 另外,我想使用Kotlin。
答案 0 :(得分:1)
如果使用Mockito,你可以这样做:
import android.location.Location
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.junit.MockitoJUnitRunner
import java.util.*
@RunWith(MockitoJUnitRunner::class)
class LocationsTest{
@Test
fun should_return_one_location() {
val location = Location("test").apply {
latitude = 1.234
longitude = 5.678
// ...
}
val mockRepository = mock(RxLocationRepository::class.java)
`when`(mockRepository.onLocationUpdate()).thenReturn(Observable.just(location))
// use the mock
}
}
我正在使用:testCompile "org.mockito:mockito-core:2.11.0"
答案 1 :(得分:0)
我需要设置不同的Dagger模块,它只是为我提供了此存储库的实现 - 它返回不同的Observable流。
我这样设置。
@Module
abstract class StubLocationRepositoryModule {
@Binds
internal abstract fun bindsRxLocationRepository(stubRxLocationRepository: StubRxLocationRepository) : RxLocationRepository
}
我刚刚在我的androidTest包中使用它。
所以我的实现是这样的:
只是一个例子:
class StubRxLocationRepository @Inject constructor(val stubLocationParameterName: String) : RxLocationRepository {
val location = Location("test").apply {
latitude = 1.234
longitude = 5.678
accuracy = 20f
time = Date().time
}
override fun onLocationUpdate(): Observable<Location> {
Log.v("StubLocationRepository", "CHOSEN PARAMETER: $stubLocationParameterName")
return when (stubLocationParameterName) {
"highFreq" -> Observable.interval(50, TimeUnit.MILLISECONDS)
.flatMap(
{
Observable.just(location)
}
)
.doOnNext{ t: Location -> Log.v("onLocationUpdate", t.toString()) }
else -> Observable.interval(1, TimeUnit.SECONDS)
.flatMap(
{
Observable.just(location)
}
)
.doOnNext{ t: Location -> Log.v("onLocationUpdate", t.toString()) }
}
}
override fun stopLocationUpdates() {
Log.v("StubLocationRepository", "stopLocationUpdates")
}
}
所以在我的Dagger组件构建器中,我公开了一个方法,它将为我提供一些参数,我将依赖于StubRxLocation实现 - 它将返回一些特定测试用例所需的流。
所以组件:
@Singleton
@Component(modules = arrayOf(StubLocationRepositoryModule::class,
LocationTestInstrumentalModule::class, StubRssiRepositoryModule::class))
interface LocationTestInstrumentalComponent{
fun locationClient(): LocationClient
@Component.Builder
interface Builder {
@BindsInstance
fun context(context: Context): Builder
@BindsInstance
fun stubLocationRepositoryParameter(stubLocationRepositoryParameter: String): Builder
fun build(): LocationTestInstrumentalComponent
}
}
因此,在每个测试中,我都可以将模拟的存储库带到这样,这样就可以用于测试用例:
@Test
fun someTest(){
val component = DaggerLocationTestInstrumentalComponent.builder().stubLocationRepositoryParameter("highFreq").context(InstrumentationRegistry.getContext()).build()
val client = component.locationClient()
//i can expose some other methods, not only this 'locationClient' in this Component to return me some classes, like this RxLocationRepository(which will behave as i want) and others
}