LoginSignup
3
1

More than 3 years have passed since last update.

Dartユニットテスト:時刻処理をテストするために日付処理のモックを作成する

Posted at

こんにちは。
人間ミスはつきものですね。
ミスを見つけるためにも、ある程度の規模や複雑性のあるコードを書いた場合、ユニットテストを書いたほうがいいと思っています。(実践できているかはさておき)。

今回、日付周りの処理を実装したのですが、この辺パターンが膨大になるのでテストを書きました。
その備忘録です。

この記事で説明すること

  • 既存機能(DateTime)を拡張する方法
  • dartのユニットテストの基本的な方法
  • ユニットテストで日付モックを使う方法(pluginなし)

既存機能(DateTime)を拡張する方法

他の言語にもありますが、dartにも既存機能を拡張する方法があります。

個人的には下記のことに気をつけています。

  • 不用意に拡張しない
  • 拡張したことがわかるように〇〇_estensionsという名前にしている
datetime_extensions.dart
extension DateTimeExtension on DateTime {
  // インスタンスメソッドの拡張
  // thisで自分自身(dateTimeインスタンス)にアクセス
  String get ymdJp => DateFormat("yyyy年M月d日", "ja_JP").format(this);

  // クラス変数
  static DateTime _customTime;
  static set customTime(DateTime customTime) {
    _customTime = customTime;
  }

  // クラスメソッドとして拡張
  static DateTime get current {
    return _customTime ?? DateTime.now();
  }
}

解説
* extension Extension名 on もとのクラス名 でクラスを拡張する
* extensionの中に、拡張したい機能を追加する(インスタンスメソッド、クラスメソッドのどちらも拡張可能)

拡張したコードの呼び出し方法

こんな感じで呼び出せます。インスタンスメソッドはわかりやすいですね。
クラスメソッドは、クラスが変わっているので注意が必要です。

あと、extensionしたファイルをimportする必要があります。

sample_widget.dart
// importの場所は人によって異なるので注意してください
import 'package:cojicaji/extension/datetime_extension.dart';
import 'package:flutter/material.dart';

class SampleWidget extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    DateTime dateTime = DateTime.now();
    return Text(dateTime.ymdJp);
  }
}
review_logic.dart
import 'package:cojicaji/extension/datetime_extension.dart';

class ReviewLogic {
  /// レビュー依頼を表示するかどうかを判定するダミーロジック
  bool isShowReview() {
    // 前回のレビュー発火から28日以上立っているか?(標準ライブラリでNヶ月計算しにくいので日付換算)
    // Yes -> レビューだす / No -> レビュー依頼ださない

    // 本日の日付と最終レビュー依頼日付を取得する。最終レビュー日付依頼のコードはダミー
    DateTime today = DateTimeExtension.current;    
    DateTime lastReviewRequestDate = getLastReviewRequestDateTime();

    Duration difference = today.difference(lastReviewRequest);
    if (difference.inDays < 28) {
      return false; // noNeedReview;
    }

    return true;
  }

}

日付モックをUnitTestする方法

サンプルコードとざっくり解説します。

  • void main() {}の中にテストを書く
  • groupを使ってテストコードをグルーピングできる。ネスト可能。
  • setUp()は、test()の前に毎回走る処理。共通する初期化などを書く
  • テストは無形関数を使って、test('testケース', () {})のように書く。日本語OK。
  • expectを使って、結果を評価する
hoge_test.dart
import 'package:cojicaji/extension/datetime_extension.dart';

void main() {
  group('レビュー依頼の判定', () {
    group('28日以上経過してる場合', () {
      setUp(() {
        // テストが1つしかないなら、ここに書く必要は本当はないが、解説の都合で記載。
        // 日付のモック更新
        var currentUtcDateTimeMock = DateTime.utc(2021, 1, 28);
        DateTimeExtension.customTime = currentUtcDateTimeMock;
      });

      test('レビュー依頼がでること', () {
        var logic = new ReviewLogic();
        var result = logic.isShowReview();
        expect(result, true);
      });

参考文献

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1