2024/11/17 Jetpack DataStoreを利用したクラスの単体テストをする
リポジトリのインターフェースは次の通りである。
code:CredentialsRepository.kt
interface CredentialsRepository {
suspend fun getCredentials(): Result<Credentials, GetCredentialError>
}
リポジトリのgetCredentials
code:Settings.kt
data class Credentials(val username: String, val password: String)
code:DataStoreCredentialsRepository.kt
class DataStoreCredentialsRepository(private val dataStore: DataStore<Preferences>) :
CredentialsRepository {
// ...
以上の状況で、クラスDataStoreCredentialsRepositoryのコンストラクタに適切なテストダブルを渡し、getCredentialsメソッドの動作を確認したい。
dataStore.dataは、Flow<Preferences>である。
疑問点
テストで、DataStoreのusernameキーやpasswordキーに値が格納されることを仮定するのは適切だろうか?
本来、適切ではない。
キーをどのように格納するのかをテストが知っていると、脆いテストになる。
→ 単一のメソッドのみをテストするのではなく、getCredentialsとupdateCredentialsの組を用いてテストするのが適切な粒度になりそう。
ただ、空のDataStoreに対するテストは書いても良さそうt6o_o6t.icon
データが一切存在しないときにgetCredentialsが失敗するのはクラス名から自明であるため
テストダブルは、.data プロパティへの参照に対しFlow<Preferences>を返すオブジェクトとしよう
ただ、Preferencesの構造を仮定することはできないので、テストダブルのFlowには値を一切 emit しないことにする
RubyのRSpecと比べて、テストを階層的に整理する能力が弱いような...? MockではなくPreferenceDataStoreFactory.createで本物のインスタンスを作ったほうが良さそう
DataStoreへの書き込み処理も再現するのは大変だ