【问题标题】:context doesn't match when testing Provider测试提供者时上下文不匹配
【发布时间】:2020-06-23 06:53:47
【问题描述】:

我编写了一个测试来检查提供程序是否按预期工作,但是在检查上下文是否与提供程序上下文匹配时出现以下异常:

══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure object was thrown running a test:
  Expected:
_InheritedProvderElement<AuthScreen>:<ChangeNotifierProvider<AuthScreen>-[GlobalKey#11403](value:
Instance of 'AuthScreen', listening to value)>
  Actual:
_DefaultInheritedProviderScopeElement<AuthScreen>:<_DefaultInheritedProviderScope<AuthScreen>(value:
Instance of 'AuthScreen', listening to value)>

When the exception was thrown, this was the stack:
#4      main.<anonymous closure> (file:///home/hannes/Documents/StudioProjects/brf/test/Authentication/authenticate_test.dart:24:5)
<asynchronous suspension>
#5      testWidgets.<anonymous closure>.<anonymous closure> (package:flutter_test/src/widget_tester.dart:140:29)
<asynchronous suspension>
#6      TestWidgetsFlutterBinding._runTestBody (package:flutter_test/src/binding.dart:699:19)
<asynchronous suspension>
#9      TestWidgetsFlutterBinding._runTest (package:flutter_test/src/binding.dart:679:14)
#10     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1079:24)
#16     AutomatedTestWidgetsFlutterBinding.runTest (package:flutter_test/src/binding.dart:1076:15)
#17     testWidgets.<anonymous closure> (package:flutter_test/src/widget_tester.dart:133:24)
#18     Declarer.test.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:171:27)
<asynchronous suspension>
#19     Invoker.waitForOutstandingCallbacks.<anonymous closure> (package:test_api/src/backend/invoker.dart:242:15)
#24     Invoker.waitForOutstandingCallbacks (package:test_api/src/backend/invoker.dart:239:5)
#25     Declarer.test.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/declarer.dart:169:33)
#30     Declarer.test.<anonymous closure> (package:test_api/src/backend/declarer.dart:168:13)
#31     Invoker._onRun.<anonymous closure>.<anonymous closure>.<anonymous closure>.<anonymous closure> (package:test_api/src/backend/invoker.dart:392:25)
#45     _Timer._runTimers (dart:isolate-patch/timer_impl.dart:398:19)
#46     _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:429:5)
#47     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
(elided 28 frames from class _FakeAsync, package dart:async, package dart:async-patch, and package stack_trace)

This was caught by the test expectation on the following line:
  file:///home/hannes/Documents/StudioProjects/brf/test/Authentication/authenticate_test.dart line 24
The test description was:
  AuthScreen provider changes value
════════════════════════════════════════════════════════════════════════════════════════════════════

另外,_childKey.currentContext 为空。我不知道这是否相关,或者是我做错了什么。

我尝试关注this guide,我的测试如下:

import 'package:brf/models/auth_screen.dart';
import 'package:brf/screens/authenticate/authenticate.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {

  setUp(() {
    AuthScreen();
  });

  testWidgets('AuthScreen provider changes value', (WidgetTester tester) async {
    final _providerKey = GlobalKey();
    final _childKey = GlobalKey();
    BuildContext context;

    await tester.pumpWidget(
      MaterialApp(
        home: ChangeNotifierProvider<AuthScreen>(
          key: _providerKey,
          create: (c) {
            context = c;
            return AuthScreen();
          },
          child: Authenticate(key: _childKey),
        ),
      ),
    );

    expect(context, equals(_providerKey.currentContext));

    expect(Provider.of<AuthScreen>(_childKey.currentContext).showSignIn, true);

    Provider.of<AuthScreen>(context, listen: false).switchScreen();
    await Future.microtask(tester.pump);

    expect(Provider.of<AuthScreen>(_childKey.currentContext).showSignIn, false);
  });
}

最后AuthScreen 看起来像这样:

import 'package:flutter/material.dart';

class AuthScreen extends ChangeNotifier{
  bool _showSignIn = true;

  bool get showSignIn => _showSignIn;

  void switchScreen(){
    _showSignIn = !_showSignIn;
    notifyListeners();
  }
}

【问题讨论】:

    标签: flutter dart flutter-provider


    【解决方案1】:

    这是您传递的空上下文的错误

    你这个: Builder(builder: (context) =&gt; Widget here

    在你想传递上下文的地方试试这样:

     MaterialApp(
            home: Builder(builder: (context) => ChangeNotifierProvider<AuthScreen>(
              key: _providerKey,
              create: (c) {
                context = c;
                return AuthScreen();
              },
              child: Authenticate(key: _childKey),
            ),
          ),
        );
    

    【讨论】:

    • 建造者应该在哪里?在 MaterialApp 之上?
    • @HannesHultergård,立即查看
    猜你喜欢
    • 2020-06-15
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 2023-03-21
    • 2022-11-19
    • 2021-12-24
    • 1970-01-01
    • 2013-09-20
    相关资源
    最近更新 更多