- こちらのチュートリアルを解説します。
- チュートリアルを読むのが早いと思いますが、概要をまとめたのでこちらもご参照ください。
前回まで
- CleanArchitectureの内側から順次実装
- Repositoryの実装完了
- Repositoryの実装のためにRepositoryの依存オブジェクトのインターフェイスを作成
- Repositoryの実装完了
今回
- Repositoryの依存オブジェクトの1つ、LocalDataSourceの実装を作成
- インターフェイスは既に作成済み
shared_preferences
- localデータ保存にはshared_prefrencesを用いる
final jsonString = sharedPreferences.getString('CACHED_NUMBER_TRIVIA');
sharedPreferences.setString(
CACHED_NUMBER_TRIVIA,
json.encode(triviaToCache.toJson()),
);
- 保存時に、JSONをStringとして保存する
- TDDではfixtureを用いる
getLastNumberTrivia
- ローカル保存されたデータの取得
- インターフェイスは非同期(Future)であるが、shared_preferencesは同期的に取得する
-
Future.value()
を用いて非同期化している
-
- インターフェイスは非同期(Future)であるが、shared_preferencesは同期的に取得する
number_trivia_local_data_source.dart
@override
Future<NumberTriviaModel> getLastNumberTrivia() {
final jsonString = sharedPreferences.getString('CACHED_NUMBER_TRIVIA');
// Future which is immediately completed
return Future.value(NumberTriviaModel.fromJson(json.decode(jsonString)));
}
例外を投げる操作のassert
- 以下のように記述する
expect(() => call(), throwsA(isA<CacheException>()));
test.dart
test('should throw a CacheException when there is not a cached value', () {
// arrange
when(mockSharedPreferences.getString(any)).thenReturn(null);
// act
// Not calling the method here, just storing it inside a call variable
final call = dataSource.getLastNumberTrivia;
// assert
// Calling the method happens from a higher-order function passed.
// This is needed to test if calling a method throws an exception.
expect(() => call(), throwsA(isA<CacheException>()));
});
学んだこと
DataSourceのアクセスメソッドを非同期としている
- DataSourceのインターフェイスは非同期メソッドを宣言する
- インターフェイスはどのような実装にも差し替えられるように作るため
- 今回仕様したsharedPreferencesは同期的にアクセスするものなので、実装内部で
Future.value()
を用いて非同期化する
例外を返すテスト
- 以下のように記述する
expect(() => call(), throwsA(isA<CacheException>()));