Flutter中通过BuildContext

时间:2019-05-23 14:30:24

标签: unit-testing dart flutter

我在Dart类中有一个方法,该方法可以接受BuildContext参数,如下所示:

class MyClass {

  <return_type> myMethodName(BuildContext context, ...) {
        ...
        doSomething
        return something;
    }
}

我想测试该方法是否按预期工作:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
...

void main() {
  MyClass sut;

  setUp(() {
    sut = MyClass();
  });

  test('me testing', () {

    var actual = sut.myMethodName(...);        

    expect(actual, something);
  });
}

当然不会,因为方法myMethodName需要参数BuildContext类型。该值可在整个应用程序本身中使用,但不确定在单元测试中从何处获取。

4 个答案:

答案 0 :(得分:7)

您实际上可以模拟BuildContext,以便测试顺利进行。我认为这更好,但可能不是您正在寻找的解决方案。

BuildContext是一个抽象类,因此无法实例化。任何抽象类都可以通过创建该类的实现来模拟。如果以您的示例为例,则代码将如下所示:

class MockBuildContext extends Mock implements BuildContext {}

void main() {
   MyClass sut;
   MockBuildContext _mockContext;

   setUp(() {
     sut = MyClass();
     _mockContext = MockBuildContext();
   });

   test('me testing', () {

   var actual = sut.myMethodName(_mockContext, ...);        

   expect(actual, something);
  });
}

答案 1 :(得分:2)

一种方法是将testWidgetsBuilder widget结合使用:

`status`=? AND `deleted`=?

答案 2 :(得分:2)

这是在测试用例中检索 BuildContext 实例的简单方法:

testWidgets('showDialog', (WidgetTester tester) async {
  await tester.pumpWidget(MaterialApp(home: Material(child: Container())));
  final BuildContext context = tester.element(find.byType(Container));

  final dialog = showDialog(
    context: context,
    builder: (context) => AlertDialog(
      content: Text('shown by showDialog'),
    ),
  );

  // apply your tests to dialog or its contents here.
});

这是受到 showDialog() 函数的 Flutter 测试用例中的 Simple dialog control test 的启发。

整个“应用程序”由 Container 框架中的 MaterialApp 小部件组成。 BuildContext 实例是通过查找与 Element 相关的 Container 实例来检索的。

答案 3 :(得分:2)

我对“surga”回答完全没问题,但在某些情况下,这还不够好。 例如,当您想将此 BuildContextInhiretedWidget 一起使用时,例如:ProviderMediaQuery

所以我建议使用 Mockito 默认生成器为您生成 BuildContext 类。

@GenerateMocks([BuildContext])
BuildContext _createContext(){
final context = MockBuildContext();
...

并将 build_runner 添加到您的 pubspec.yaml

dev_dependencies:
  flutter_test:
    sdk: flutter
  build_runner: any //use any version you want

然后运行这个命令:

flutter packages pub run build_runner build

现在您可以从 context 类创建一个 MockBuildContext 对象,因为它通常是从 MaterialApp 创建的。

@GenerateMocks([BuildContext])
BuildContext _createContext(){
  final context = MockBuildContext();
  final mediaQuery = MediaQuery(
    data: MediaQueryData(),
    child: const SizedBox(),
  );
  when(context.widget).thenReturn(const SizedBox());
  when(context.findAncestorWidgetOfExactType()).thenReturn(mediaQuery);
  when(context.dependOnInheritedWidgetOfExactType<MediaQuery>())
      .thenReturn(mediaQuery);
  return context;
}

注意:不需要为此 Mock 添加 when..thenReturn,这取决于您的需要。