如何在Android MVP Clean体系结构中测试注入到存储库中的SharedReference
我在数据存储中测试SharedReference时遇到了一个问题。在实际的数据存储中,我实现了三个参数,其中包括SharedReference 在本例中,我希望存储值,并获取该值。嘲笑在这里没有帮助 模拟不能传播代码将使用的实际值。第二部分如何在Android MVP Clean体系结构中测试注入到存储库中的SharedReference,android,unit-testing,kotlin,spek,Android,Unit Testing,Kotlin,Spek,我在数据存储中测试SharedReference时遇到了一个问题。在实际的数据存储中,我实现了三个参数,其中包括SharedReference 在本例中,我希望存储值,并获取该值。嘲笑在这里没有帮助 模拟不能传播代码将使用的实际值。第二部分 class FooDataStoreTest : Spek({ given("a foo data store") { val schedulerRule = TestSchedulerRule() val service: FooRest
class FooDataStoreTest : Spek({
given("a foo data store") {
val schedulerRule = TestSchedulerRule()
val service: FooRestService = mock()
val context: Context = mock()
val gson: Gson = mock()
val appFooPreference: SharedPreferences = mock()
var appFooSessionStoreService: AppFooSessionStoreService? = null
var fooStoredLocationService: FooStoredLocationService? = null
beforeEachTest {
appFooSessionStoreService = AppFooSessionStoreService.Builder()
.context(context)
.gson(gson)
.preference(appFooPreference)
.build()
fooStoredLocationService = FooStoredLocationService(appFooSessionStoreService)
}
val longitude = 106.803090
val latitude = -6.244285
on("should get foo service with request longitude $longitude and latitude $latitude") {
it("should return success") {
with(fooStoredLocationService) {
val location = Location()
location.latitude = latitude
location.longitude = longitude
// i want to store location in this
fooStoredLocationService?.saveLastKnownLocation(location)
// and retrieve in below code
val l = fooStoredLocationService?.lastKnownLocation
val dataStore = FooDataStore(service, preference, fooStoredLocationService!!)
service.getFooService(longitude, longitude) willReturnJust
load(FooResponse::class.java, "foo_response.json")
val testObserver = dataStore.getFooService().test()
schedulerRule.testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
testObserver.assertNoErrors()
testObserver.awaitTerminalEvent()
testObserver.assertComplete()
testObserver.assertValue { actual ->
actual == load(FooResponse::class.java, "foo_response.json")
}
}
}
}
afterEachTest {
appFooSessionStoreService?.clear()
fooStoredLocationService?.clear()
}
}})
这个数据存储看起来像
open class FooDataStore @Inject constructor(private val fooRestService: FooRestService,
private val fooPreference: FooPreference,
private val fooLocation: fooStoredLocationService) : FooRepository {
private val serviceLocation by lazy {
fooLocation.lastKnownLocation
}
override fun getFooService(): Single<FooResponse> {
safeWith(serviceLocation, {
return getFooLocal(it).flatMap({ (code, message, data) ->
if (data != null) {
Single.just(FooResponse(code, message, data))
} else {
restService.getFooService(it.longitude, it.latitude).compose(singleIo())
}
})
})
return Single.error(httpExceptionFactory(GPS_NOT_SATISFYING))
}
openclass FooDataStore@Inject构造函数(私有val fooRestService:fooRestService,
私人val fooPreference:fooPreference,
私有位置:FoodStoredLocationService):FoodRepository{
专用val serviceLocation(按惰性){
最新位置
}
覆盖趣味getFooService():单个{
safeWith(服务位置{
返回get傻瓜本地(it).flatMap({(代码、消息、数据)->
如果(数据!=null){
Single.just(FooResponse(代码、消息、数据))
}否则{
restService.getFooService(it.longitude,it.latitude).compose(singleIo())
}
})
})
返回单个错误(httpExceptionFactory(GPS不满足))
}
}
实际上,我想从这个字段serviceLocation
中获取值。任何人都有办法做一些测试吗?任何建议都非常欢迎
谢谢 我建议您不要直接依赖
SharedReferences
,而是使用一些接口LocalStorage
,这样您就可以在代码中使用SharedRefersLocalStorage
,在测试中使用TestLocalStorage
SharedPrefersLocalStorage
将在引擎盖下使用SharedPreferences
和TestLocalStorage
一些Map
实现
举个简单的例子:
// You may add other type, not Int only, or use the String and convert everything to String and back
interface LocalStorage {
fun save(key: String, value: Int)
fun get(key: String): Int?
}
class SharedPrefsLocalStorage(val prefs: SharedPreferences) : LocalStorage {
override fun save(key: String, value: Int) {
with(prefs.edit()){
putInt(key, value)
commit()
}
}
override fun get(key: String): Int? = prefs.getInteger(key)
}
class TestLocalStorage : LocalStorage {
val values = mutableMapOf<String, Any>()
override fun save(key: String, value: Int) {
values[key] = value
}
override fun get(key: String): Int? = map[value] as Int?
}
//您可以添加其他类型,而不仅仅是Int类型,或者使用字符串并将所有内容转换为String和back
接口本地存储{
趣味保存(键:字符串,值:Int)
有趣的获取(键:字符串):Int?
}
类SharedPrefersLocalStorage(val prefs:SharedPreferences):LocalStorage{
覆盖乐趣保存(键:字符串,值:Int){
使用(prefs.edit()){
putInt(键、值)
提交()
}
}
重写fun get(键:字符串):Int?=prefs.getInteger(键)
}
类TestLocalStorage:LocalStorage{
val values=mutableMapOf()
覆盖乐趣保存(键:字符串,值:Int){
值[键]=值
}
覆盖乐趣获取(键:字符串):Int?=将[值]映射为Int?
}
那么,您的意思是说,通过使用接口和实现级别将返回用于传播伪值的特定值吗?我已经考虑过了。但是,如果我们有另一种可能比这更好的方法,那就好了。不管怎么说,那都是可行的。AndroidX测试是否允许直接测试共享pref?