如何在 Flutter 中测试使用 DateTime.now 的代码?

Jor*_*ies 18 flutter flutter-test

我有这门课:

import 'package:flutter/material.dart';

class AgeText extends StatelessWidget {
  final String dateOfBirth;

  const AgeText({Key key, @required this.dateOfBirth}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final age = _calculateAge();
    return Text(age.toString());
  }

  int _calculateAge() {
    final dateOfBirthDate = DateTime.parse(dateOfBirth);
    final difference = DateTime.now().difference(dateOfBirthDate);
    final age = difference.inDays / 365;

    return age.floor();
  }
}
Run Code Online (Sandbox Code Playgroud)

我想测试它是否在传递出生日期时产生正确的年龄。在 Flutter 中执行此操作的最佳方法是什么?


解决方案:对于那些感兴趣的人,这是使用@Günter Zöchbauer 对时钟包的建议的解决方案。

我的小部件类:

import 'package:flutter/material.dart';
import 'package:clock/clock.dart';

class AgeText extends StatelessWidget {
  final String dateOfBirth;
  final Clock clock;

  const AgeText({Key key, @required this.dateOfBirth, this.clock = const Clock()}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final age = _calculateAge();
    return Text(age.toString());
  }

  int _calculateAge() {
    final dateOfBirthDate = DateTime.parse(dateOfBirth);
    final difference = clock.now().difference(dateOfBirthDate);
    final age = difference.inDays / 365;

    return age.floor();
  }
}
Run Code Online (Sandbox Code Playgroud)

和我的测试课:

import 'package:clock/clock.dart';
import 'package:flutter/material.dart';
import 'package:flutter_app/age.dart';
import 'package:flutter_test/flutter_test.dart';

void main() {
  testWidgets("shows age 30 when date of birth is 30 years ago", (WidgetTester tester) async {
    final mockClock = Clock.fixed(DateTime(2000, 01, 01));
    final testableWidget = MaterialApp(
      home: AgeText(
        dateOfBirth: "1970-01-01T00:00:00",
        clock: mockClock,
      ),
    );

    await tester.pumpWidget(testableWidget);

    expect(find.text("30"), findsOneWidget);
  });
}
Run Code Online (Sandbox Code Playgroud)

Iir*_*kka 26

\n

正如 G\xc3\xbcnter 所说,Dart 团队维护的时钟包提供了一种非常巧妙的方法来实现这一目标。

\n

正常使用:

\n
import \'package:clock/clock.dart\';\n\nvoid main() {\n  // prints current date and time\n  print(clock.now());\n}\n
Run Code Online (Sandbox Code Playgroud)\n

覆盖当前时间:

\n
import \'package:clock/clock.dart\';\n\nvoid main() {\n  withClock(\n    Clock.fixed(DateTime(2000)),\n    () {\n      // always prints 2000-01-01 00:00:00.\n      print(clock.now());\n    },\n  );\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我在我的博客上更详细地介绍了这一点。

\n

对于小部件测试,您需要将pumpWidget,pump和包装expectwithClock回调中。

\n

  • 优秀的文章。 (6认同)

Gün*_*uer 9

如果您根据代码使用时钟包,则DateTime.now()可以轻松模拟它。

我认为没有包装提供的DateTime.now()licke包装的好方法clock


Ada*_*aka 5

正如这里提到的:https : //stackoverflow.com/a/63073876/2235274在 DateTime 上实现扩展。

extension CustomizableDateTime on DateTime {
  static DateTime _customTime;
  static DateTime get current {
    return _customTime ?? DateTime.now();
  }

  static set customTime(DateTime customTime) {
    _customTime = customTime;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后只需CustomizableDateTime.current在生产代码中使用。您可以修改这样的测试返回值:CustomizableDateTime.customTime = DateTime.parse("1969-07-20 20:18:04");。无需使用第三方库。

  • 更简洁地说:`返回customTime ?? 日期时间.now();` (2认同)
  • 这看起来像是代码味道。为了测试目的而修改代码是一种不好的做法。此外,customTime 可能会导致错误。您可以将 DateTime.now() 包装在仅包含返回当前值的函数的类中。然后在测试中模拟此类以返回您需要的任何内容。 (2认同)