简体   繁体   中英

Flutter mocked clock (using withClock) behave inconsistenly when app starts with WidgetsFlutterBinding.ensureInitialized()

If flutter app starts with:

void main() {
  WidgetsFlutterBinding.ensureInitialized();

Then clock.now() prints not mocked value if outside of build method.

Since I am using withClock in my tests, it makes my app unable to be properly tested as sometimes clock.now() returns mocked value, and sometimes real current time.

Please find the following example, and note that _printClockNow prints DateTime.now() , but it should print year 1990.

If you removed line WidgetsFlutterBinding.ensureInitialized() then it works as expected.

Minimum reproduceable code:

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

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  
  withClock(Clock.fixed(DateTime(1990)), () {
    runApp(const MyApp());
  });
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void _printClockNow() {
    print('_printClockNow is: ${clock.now()}'); // prints real NOW
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    print('build clock.now() is: ${clock.now()}'); // prints mocked NOW

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[Dummy()],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _printClockNow,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

class Dummy extends StatelessWidget {
  @override
  Widget build(Object context) {
    return Text('t: ${clock.now()}');
  }
}

Try with putting WidgetsFlutterBinding inside withClock .

void main() {
  withClock(Clock.fixed(DateTime(1990)), () {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(const MyApp());
  });
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM