首页 > 解决方案 > 在集成测试期间意外处置小部件

问题描述

注意:在正常的应用程序运行中一切正常,问题仅在运行集成测试时发生。


我们使用的是 Flutter Channel 稳定版 2.2.3,对于集成测试,我们使用的是来自 Flutter SDK 的版本:“integration_test: sdk:flutter”</p>

在通过 Screen#1 的 dispose() 方法从 Screen#1 导航到 Screen#2Navigator.of(context).pushNamed(ScreenTwo, arguments: counterProvider);后,将被调用。我们使用 Provider 进行状态管理,Provider 在 Screen#1 上创建并传递给 Screen#2。现在显示以下错误:

错误:处理后使用了 CounterProvider。一旦在 CounterProvider 上调用了 dispose(),就不能再使用它。

这是因为 Screen#1 页面在导航到 Screen#2 页面后被处理。


有没有人遇到过这个问题,或者有没有人知道我们如何防止在导航后调用处置的方法?</p>

它只发生在集成测试期间。

项目链接:https ://bitbucket.org/UrimGashiABC/test-dispose-issuesample/src/master/

屏幕#1 类:

class ScreenOnePage extends StatefulWidget {
  @override
  _ScreenOnePageState createState() => _ScreenOnePageState();
}

class _ScreenOnePageState extends State<ScreenOnePage> {

  @override
  Widget build(BuildContext context) {
    CounterProvider counterProvider = Provider.of<CounterProvider>(
      context,
      listen: true,
    );
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Screen #1',
            ),
            SizedBox(
              height: 150,
            ),
            Text(
              '${counterProvider.counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
            SizedBox(
              height: 150,
            ),
            TextButton(
              key: const Key('screen_one_text_button'),
              onPressed: () {
                Navigator.of(context).pushNamed(ScreenTwo, arguments: counterProvider);
              },
              child: Text('Go to screen#2'),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        key: const Key('screen_one_floating_button'),
        onPressed: () => counterProvider.increaseCounter(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), //
    );
  }
}

屏幕#2 类:

class ScreenTwoPage extends StatefulWidget {
  @override
  _ScreenTwoPageState createState() => _ScreenTwoPageState();
}

class _ScreenTwoPageState extends State<ScreenTwoPage> {
  @override
  Widget build(BuildContext context) {
    CounterProvider counterProvider = Provider.of<CounterProvider>(
      context,
      listen: false,
    );
    return Scaffold(
      appBar: AppBar(),
      body: Container(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text(
                'Screen #2',
                key: const Key('screen_two_title'),
              ),
              SizedBox(
                height: 150,
              ),
              Text(
                'Counter: ${counterProvider.counter}',
                key: const Key('screen_two_counter'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

提供者类:

class CounterProvider extends ChangeNotifier{
    int counter = 0;

    void increaseCounter(){
      counter++;
      notifyListeners();
    }
}

测试类:

void main(){
    IntegrationTestWidgetsFlutterBinding.ensureInitialized();

    testWidgets('counter test', (WidgetTester tester) async {
      app.main();
      await tester.pumpAndSettle();
      final Finder screenOneButton = find.byKey(const Key('screen_one_text_button'));
      final Finder screenOneFloatingButton = find.byKey(const Key('screen_one_floating_button'));
      final Finder screenTwoTitle = find.byKey(const Key('screen_two_title'));
      final Finder screenTwoCounter = find.byKey(const Key('screen_two_counter'));

      await tester.tap(screenOneFloatingButton);
      await tester.tap(screenOneButton);

      await tester.pumpAndSettle();

      expect(screenTwoTitle, findsOneWidget);
    });

}

标签: flutterdartflutter-integration-test

解决方案


推荐阅读