Cómo burlarse del repository reactivo que devuelve Observable

Entonces tengo repository, que proporciona el Observable al cliente. ¿Existe alguna forma de burlar este repository, así que no necesito enviar la location desde mi emulador o usar el dispositivo real para get alguna location?

Así es como se ve la interfaz:

interface RxLocationRepository { @SuppressLint("MissingPermission") fun onLocationUpdate(): Observable<Location> fun stopLocationUpdates() } 

En mi lado del cliente lo uso así:

 class LocationManager( val rxLocationRepository: RxLocationRepository){ private fun appendGeoEvent(location: Location) { val locationGeoEvent = LocationGeoEvent( accuracy = location.accuracy.toDouble(), latitude = location.latitude, longitude = location.longitude, timestampGeoEvent = location.time ) processGeoEvent(locationGeoEvent) } compositeDisposable.add(rxLocationRepository.onLocationUpdate() .subscribe(Consumer { location -> appendGeoEvent(location) })) .... 

Entonces envío esta location obtenida a mi método appendGeoEvent.

Puedo usar, por ejemplo, Mockito, pero no sé cómo burlar este repository para poder usar las ubicaciones falsas. Además, quiero usar Kotlin.

Si usa Mockito, podría hacer algo como esto:

 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 } } 

Estoy usando: testCompile "org.mockito:mockito-core:2.11.0"

Necesitaba configurar un module de Dagger diferente, que solo me proporcionara la implementación de este repository; devuelve una secuencia de Observable diferente.

Lo configuré así.

 @Module abstract class StubLocationRepositoryModule { @Binds internal abstract fun bindsRxLocationRepository(stubRxLocationRepository: StubRxLocationRepository) : RxLocationRepository } 

Solo estaba usando esto en mi package androidTest en el componente.

Entonces mi implementación fue así:

solo un ejemplo:

 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") } } 

Entonces, en mi creador de Dagger Component expongo un método que me proporcionará algún parámetro del que dependeré en la implementación de StubRxLocation – me devolverá alguna secuencia que necesito para un caso de testing específico.

Entonces el componente:

 @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 } } 

Entonces en cada testing puedo traer el repository simulado así, que estará listo para usar en ese caso de testing:

 @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 }