2024/11/17 Jetpack DataStoreを利用したクラスの単体テストをする
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)
リポジトリの実装では、DataStoreへの参照はコンストラクタで渡せるようにした。
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 しないことにする
Androidの単体テストケース名を日本語で書きたい
RubyのRSpecと比べて、テストを階層的に整理する能力が弱いような...?
Nested Testsで欲しい機能が使えそう!
https://junit.org/junit5/docs/current/user-guide/#writing-tests-nested
MockではなくPreferenceDataStoreFactory.createで本物のインスタンスを作ったほうが良さそう
DataStoreへの書き込み処理も再現するのは大変だ