gpt4 book ai didi

android - 围绕 SharedPreference 对辅助类进行单元测试

转载 作者:行者123 更新时间:2023-12-02 12:05:54 27 4
gpt4 key购买 nike

我有一个帮助类来将用户对象保存到共享首选项。我用过 serialize(): String函数和 create(serializedString: String)我的 User 中的函数数据模型。他们使用 Gson 序列化程序,并且按照单元测试的建议运行良好。

现在我的助手类被称为 SharedPreferenceUserStore.kt这需要 Context目的。代码是:

class SharedPreferenceUserStore(context: Context) {
companion object {
val TAG = SharedPreferenceUserStore::class.java.simpleName
}

var userLocalSharedPref: SharedPreferences =
context.getSharedPreferences(USER_LOCAL_STORE_SHARED_PREF_NAME, Context.MODE_PRIVATE)

/*
Store the required data to shared preference
*/
@SuppressLint("ApplySharedPref")
fun storeUserData(user: User) {
val userLocalDatabaseEditor = userLocalSharedPref.edit()
val serializedData = user.serialize()

userLocalDatabaseEditor.putString(
USER_LOCAL_STORE_SHARED_PREF_SERIALIZED_DATA_KEY,
serializedData
)
if (userLocalDatabaseEditor.commit()) {
Log.d(TAG, " Store Commit return true")
}
}


/*
Clear all the locally stored data from the shared pref
*/
@SuppressLint("ApplySharedPref")
fun clearUserData() {
val userLocalDatabaseEditor = userLocalSharedPref.edit()
userLocalDatabaseEditor.clear()
userLocalDatabaseEditor.commit()
}

fun getLoggedInUser(): User? {
val stringUser = userLocalSharedPref.getString(
USER_LOCAL_STORE_SHARED_PREF_SERIALIZED_DATA_KEY, "")

return if (stringUser==null || stringUser == ""){
null
} else{
User.create(stringUser)
}
}

我已经为这个助手类编写了一些单元测试,如下所示:
@RunWith(JUnit4::class)
class SharedPreferenceUserStoreTest {

lateinit var sharedPreferenceUserStore: SharedPreferenceUserStore
lateinit var user: User

//to be mocked
lateinit var sharedPreferences: SharedPreferences
lateinit var sharedPreferencesEditor: SharedPreferences.Editor
lateinit var context: Context

@Before
fun setUp() {
//mocking Context and SharedPreferences class
context = mock(Context::class.java)
sharedPreferences = mock(SharedPreferences::class.java)
sharedPreferencesEditor = mock(SharedPreferences.Editor::class.java)

//specifying that the context.getSharedPreferences() method call should return the mocked sharedpref
`when`<SharedPreferences>(context.getSharedPreferences(anyString(), anyInt()))
.thenReturn(sharedPreferences)
//specifying that the sharedPreferences.edit() method call should return the mocked sharedpref editor
`when`(sharedPreferences.edit()).thenReturn(sharedPreferencesEditor)
//specifying that the sharedPreferencesEditor.putString() method call should return the mocked sharedpref Editor
`when`(sharedPreferencesEditor.putString(anyString(), anyString())).thenReturn(
sharedPreferencesEditor
)
`when`(sharedPreferences.getString(anyString(), anyString())).thenReturn("")

//instantiating SharedPreferenceUserStore from the mocked context
sharedPreferenceUserStore = SharedPreferenceUserStore(context)


user = User(
35,
"Prashanna Bhandary",
"prashanna.bhandary@gmail.com",
"dd58a617ea618010c2052cb54079ad67.jpeg",
"98********",
"test address 01",
1,
"yes",
"2019-08-30 04:56:43",
"2019-08-30 05:14:47",
0
)
}

@After
fun tearDown() {
}

@Test
fun passUser_storeUserData() {
sharedPreferenceUserStore.storeUserData(user)

verify(sharedPreferencesEditor).putString(
Constants.USER_LOCAL_STORE_SHARED_PREF_SERIALIZED_DATA_KEY,
user.serialize()
)
verify(sharedPreferencesEditor).commit()
}

@Test
fun testClearUserData() {
sharedPreferenceUserStore.clearUserData()

verify(sharedPreferencesEditor).clear()
}


@Test
fun testGetLoggedInUser_storeNotCalled() {
//calling getLoggedInUser() without calling storeUserData() should give null
assertEquals(null, sharedPreferenceUserStore.getLoggedInUser())
//verify that getString() was called on the shared preferences
verify(sharedPreferences).getString(Constants.USER_LOCAL_STORE_SHARED_PREF_SERIALIZED_DATA_KEY, "")
}

@Test
fun testGetLoggedInUser_storeCalled(){

//call getLoggedInUser(), we are expecting null
assertNull(sharedPreferenceUserStore.getLoggedInUser())

//verify that getString() was called on the shared preferences
verify(sharedPreferences).getString(Constants.USER_LOCAL_STORE_SHARED_PREF_SERIALIZED_DATA_KEY, "")
}
}

因为我对单元测试和模拟库(如 Mockito)真的很陌生.现在我的问题是 我的测试有什么好处吗? 我想测试 getLoggedInUser()我的助手类的功能正在做它应该做的事情(即,如果共享首选项有它,请登录用户),我该怎么做?

此外,建议我对我的测试或助手类本身进行任何改进。谢谢你。

最佳答案

判断你的测试是什么——一个在主机上运行的单元测试,它带有用 Mockito 模拟的 Android 依赖项——它看起来很好,就像你所期望的那样。

不过,此类测试的效益与努力比值得商榷。我个人认为对 进行这样的测试会更有值(value)。真实 SharedPreferences在设备上实现,并在 上断言实际副作用而不是在模拟上进行验证。与模拟测试相比,这有几个好处:

  • 您不必重新实现 SharedPreferences mock
  • 你知道SharedPreferenceUserStore将与真正的 SharedPreferences 一起使用实现

  • 但是 ,这样的测试也有一个值得商榷的效益与努力比。对于一个单独的开发者项目,想想什么样的测试是 最重要的 .你的时间是有限的,所以你只有时间花在编写最重要的测试上。

    最重要的测试类型是测试您的应用程序 以您的用户使用它的相同方式 .换句话说,写高级 UI Automator测试。您可以根据需要编写多少个模拟或设备上的单元测试。如果您不测试您的整个应用程序作为一个整体是否有效, 你不会知道它有效 .如果你不知道你的应用程序作为一个整体可以工作,你就不能发布它。因此,您必须以某种方式完整地测试您的应用程序。随着您添加越来越多的功能,手动快速完成变得非常费力。持续测试您的应用程序的唯一方法是自动化您的应用程序的高级 UI 测试。这样,您还将获得 的代码覆盖率事项 .

    值得指出的高级 UI 测试的一大好处是,每当您更改应用程序中的某些实现细节时,您都不必更改它们。如果你有很多模拟单元测试,你将不得不在重构真正的应用程序代码时花费大量时间来重构你的单元测试,这可能非常耗时,因此如果你是一个单独的开发人员,这不是一个好主意。您的 用户界面自动化 测试不依赖于低级实现细节,因此即使您更改实现细节也将保持不变。

    例如,也许将来你想使用 Room from Android Jetpack存储您的用户数据而不是 SharedPreference .您将能够做到这一点,而无需更改您的高级 UI 测试。他们将成为 的好方法回归测试这样的变化。如果您只有模拟单元测试,它将是 批号重写所有相关单元测试以使用 Room 的工作量反而。

    关于android - 围绕 SharedPreference 对辅助类进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58485875/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com