Нежелательное удаление виджета во время интеграционного теста

Примечание. Все работает нормально при обычном запуске приложения, проблема возникает только во время выполнения интеграционного теста.


Мы используем стабильную версию Flutter Channel 2.2.3, а для интеграционного теста - версию из flutter SDK: «integration_test: sdk: flutter»

После перехода от экрана №1 к экрану №2 через Navigator.of(context).pushNamed(ScreenTwo, arguments: counterProvider);вызывается метод dispose () экрана №1. Мы используем Provider для управления состоянием, провайдер создается на экране №1 и передается на экран №2. Теперь отображается ошибка ниже:

Ошибка: CounterProvider использовался после удаления. После того, как вы вызвали метод dispose () для CounterProvider, его больше нельзя использовать.

И это происходит потому, что страница экрана №1 удаляется после перехода на страницу экрана №2.


Кто-нибудь сталкивался с этой проблемой или кто-нибудь знает, как мы можем предотвратить вызов удаленного метода после навигации?


Это происходит только во время интеграционного теста.

Ссылка на проект: 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);
    });

}

0 ответов

Другие вопросы по тегам