Нежелательное удаление виджета во время интеграционного теста
Примечание. Все работает нормально при обычном запуске приложения, проблема возникает только во время выполнения интеграционного теста.
Мы используем стабильную версию 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);
});
}