🥰
Supabaseでテストコード書けませんか?
試しにやってみた
fake_cloud_firestoreみたいに、モックのパッケージが内容だ....
ないなら、テスト用のテーブル作って入れていいのではと思った?
とりあえず作ってみる。関数を作ってみよう。test_apiフォルダを作成して、テストコード用のINSERTできるクラスを作成。実行すると本当に保存しちゃいます😅
test_api
import 'package:supabase_flutter/supabase_flutter.dart';
final class TodoAPi {
final supabase = Supabase.instance.client;
Future<void> insertTodo({required String title}) async {
// 日本時間のtimestampzを作成
final now = DateTime.now().toUtc().add(const Duration(hours: 9));
final response = await supabase.from('dev_todo').insert({
'title': title,
'created_at': now.toIso8601String(),
});
}
}
todo_api_test.dart
をtest/
ディレクトリ配下に作成する。
テストコードを書くところでは、.env
から読み込めなかった😅
URLとanonKyeを直接ハードコーディングしている。
idは自動連番なので、自動生成されるから引数で渡す必要はなし。タイムスタンプもメソッドの中に書いてるので、引数で渡す必要はなし。引数には、タイトルだけ渡します。
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:workstream_prod/application/test_api/todo_api.dart';
void main() {
setUpAll(() async {
// Set initial values for shared preferences
SharedPreferences.setMockInitialValues({});
const url = 'https:/**************';
const anonKey =
'eyJhbGciOiJIU**********';
await Supabase.initialize(url: url, anonKey: anonKey);
});
test('TodoAPIのテスト', () async {
final todoApi = TodoAPi();
await todoApi.insertTodo(title: '宿題をする');
});
}
テストを実行する。
やって良いのか。実際に保存されているので、成功していることになる。
でもやはりモックがいいな
Supabase関係ないコードで作るくしかないですね。同じデータ型の値を渡して、期待通りの値が渡されているモックを作るしかなさそう。mockito
を使ってみた。
新しく専用のファイルを作成
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
import 'mock_todo_test.mocks.dart';
abstract class Todo {
Map<String, dynamic> insertTodo({required String title});
}
([Todo])
void main() {
test('MockTodo insertTodo test', () {
// Arrange
var mockTodo = MockTodo();
when(mockTodo.insertTodo(title: anyNamed('title'))).thenAnswer((_) {
return {
'id': 1,
'title': 'Test Title',
'created_at': DateTime.now().toIso8601String(),
};
});
/// [Act]
/// Actとは、テスト対象のメソッドを呼び出すことです。
var result = mockTodo.insertTodo(title: 'Test Title');
/// [Assert]
/// Assertとは、テスト結果を検証することです。
expect(result['id'], 1);
expect(result['title'], 'Test Title');
// Verify the method call.
verify(mockTodo.insertTodo(title: 'Test Title')).called(1);
});
}
自動生成のコマンドを実行する:
flutter pub run build_runner watch --delete-conflicting-outputs
実行結果:
一応成功しましたね😅
まとめ
Supabaseの単体テスト(UnitTest)かな...
書く方法はまだないのかもしれない。そもそもテストとはなんのためにするのか?
単純に書いた関数が、シナリオ通りに実行されているか確かめるためでしょうけどね。
最近読んだ本によると
単体テストの定義には様々なものがあります。本質的ではないものを除くと、 単体テスト として定義されるテストには次に挙げる 3 つの重要な性質がすべて備えられていること になります。つまり、自動化されていて、次の 3 つの性質をすべて備えるものが単体テストとな るのです :
- 「単体(unit)」と呼ばれる少量のコードを検証する
- 実行時間が短い
- 隔離された状態で実行される
Discussion