飞镖/颤音小部件:获取使用Kisweb的路径的测试覆盖范围

发布于 2025-02-06 17:46:10 字数 1583 浏览 3 评论 0原文

我想测试并涵盖使用KisWeb的小部件的这两个路径。班级看起来像这样:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    if (kIsWeb) {
      return Text("I'm web");
    } else {
      return Text("I'm not web");
    }
  }
}

搜索一段时间后,我找到了一种在这里进行测试的方法:在Flutter中

这是我写的测试课:

 class MockAppService extends Mock implements AppService {}
    
         void main() {
          final mockAppService = MockAppService();
          when(mockAppService.getkIsWeb())
              .thenAnswer((realInvocation) => true);
        
          testWidgets("add item", (WidgetTester tester) async {
            await tester.pumpWidget(MaterialApp(
              title: 'Flutter Demo',
              home: Scaffold(
                appBar: AppBar(
                  title: Text("title"),
                ),
                body: Center(
                  child: Text("message"),
                ),
              ),
            ));
            final PaymentPageState myWidgetState = tester.state(find.byType(PaymentPage));
            expect(find.byType(PaymentPage), findsOneWidget);
          });
        }

但是我得到了错误

类型的'null'不是类型'bool'的亚型

我的AppService类,抽象类看起来像这样,

abstract class IAppService {
  bool getkIsWeb();
}

class AppService implements IAppService {
  bool getkIsWeb() {
    return kIsWeb;
  }
}

我是新手扑来,不知道很多事情。请帮忙。

I want to test and cover both paths of a widget that uses kIsWeb. the class looks like this :

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    if (kIsWeb) {
      return Text("I'm web");
    } else {
      return Text("I'm not web");
    }
  }
}

After searching a while I found a way to test this here : Testing kIsWeb constant in flutter

This is the Test class that I wrote :

 class MockAppService extends Mock implements AppService {}
    
         void main() {
          final mockAppService = MockAppService();
          when(mockAppService.getkIsWeb())
              .thenAnswer((realInvocation) => true);
        
          testWidgets("add item", (WidgetTester tester) async {
            await tester.pumpWidget(MaterialApp(
              title: 'Flutter Demo',
              home: Scaffold(
                appBar: AppBar(
                  title: Text("title"),
                ),
                body: Center(
                  child: Text("message"),
                ),
              ),
            ));
            final PaymentPageState myWidgetState = tester.state(find.byType(PaymentPage));
            expect(find.byType(PaymentPage), findsOneWidget);
          });
        }

but I get the error

type 'Null' is not a subtype of type 'bool'

My AppService class and the abstract class looks like this,

abstract class IAppService {
  bool getkIsWeb();
}

class AppService implements IAppService {
  bool getkIsWeb() {
    return kIsWeb;
  }
}

I'm new to Flutter and does not know a lot of things. please help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

柒七 2025-02-13 17:46:11

您发现有关如何测试KisWeb的解决方案应起作用,但是您必须了解整个图片。

首先,这种方法背后的主要思想是,将应用程序是否在Web上运行,从窗口小部件中运行,而不是直接在Widget的构建方法中使用Kisweb

因此,引入了一个名为iappservice的接口,并且类AppService实现了此接口。该接口实际上并不需要,我将直接在我的示例中使用AppService类。

您的小部件应使用AppService的实例,并在其上使用getKisweb,而不是直接使用kisweb常数。有很多方法可以将实例提供给小部件。使用构造函数参数是最简单的参数之一,但是您可能希望在将来查看依赖项注入或状态管理解决方案。

class MyWidget extends StatelessWidget {
  const MyWidget({Key? key, required this.appService}) : super(key: key);

  final AppService appService;

  @override
  Widget build(BuildContext context) {
    if (appService.getKIsWeb()) {
      return const Text('I\'m web');
    } else {
      return const Text('I\'m not web');
    }
  }
}

class AppService {
  bool getKIsWeb() {
    return kIsWeb;
  }
}

最后,并非最不重要的一点。测试小部件时,您将对AppService类的模拟实现,该类别在调用getKisWeb时返回true或false,根据您的想法。

class MockAppService extends Mock implements AppService {}

void main() {
  testWidgets('Test web widget', (WidgetTester tester) async {
    final mockAppService = MockAppService();
    when(() => mockAppService.getKIsWeb()).thenReturn(true);

    await tester.pumpWidget(
      MaterialApp(
        title: 'Flutter Demo',
        home: Scaffold(
          body: MyWidget(
            appService: mockAppService,
          ),
        ),
      ),
    );

    final webTextFinder = find.text('I\'m web');
    expect(webTextFinder, findsOneWidget);
  });

  testWidgets('Test not web widget', (WidgetTester tester) async {
    final mockAppService = MockAppService();
    when(() => mockAppService.getKIsWeb()).thenReturn(false);

    await tester.pumpWidget(
      MaterialApp(
        title: 'Flutter Demo',
        home: Scaffold(
          body: MyWidget(
            appService: mockAppService,
          ),
        ),
      ),
    );

    final webTextFinder = find.text('I\'m not web');
    expect(webTextFinder, findsOneWidget);
  });
}

请注意,我在这里使用的无酒精而不是Mockito。但是你应该明白。

当(()=> mockAppService.getKisWeb())。thenreturn(false);是定义模拟行为的无用方法。 https://pub.dev/packages/mocktail

The solution you found about how to test kIsWeb should work, but you have to understand the whole picture.

First of all, the main idea behind this approach is, to move the responsibility to decide, whether the application runs on the web or not, out of the widget and not use kIsWeb directly in the widget's build method.

Therefore an interface named IAppService is introduced and the class AppService implements this interface. The interface is not really needed and I will work with the AppService class directly in my example.

Your widget should use an instance of AppService and call getKIsWeb on it, instead of using the kIsWeb constant directly. There are many ways to provide the instance to the widget. Using a constructor parameter is one of the easiest, but you may want to take a look at dependency injection or state management solutions in the future.

class MyWidget extends StatelessWidget {
  const MyWidget({Key? key, required this.appService}) : super(key: key);

  final AppService appService;

  @override
  Widget build(BuildContext context) {
    if (appService.getKIsWeb()) {
      return const Text('I\'m web');
    } else {
      return const Text('I\'m not web');
    }
  }
}

class AppService {
  bool getKIsWeb() {
    return kIsWeb;
  }
}

And last not least. When you test your widget, you give it a mocked implementation of the AppService class, which returns either true or false when getKIsWeb gets called, depending on what you want to test.

class MockAppService extends Mock implements AppService {}

void main() {
  testWidgets('Test web widget', (WidgetTester tester) async {
    final mockAppService = MockAppService();
    when(() => mockAppService.getKIsWeb()).thenReturn(true);

    await tester.pumpWidget(
      MaterialApp(
        title: 'Flutter Demo',
        home: Scaffold(
          body: MyWidget(
            appService: mockAppService,
          ),
        ),
      ),
    );

    final webTextFinder = find.text('I\'m web');
    expect(webTextFinder, findsOneWidget);
  });

  testWidgets('Test not web widget', (WidgetTester tester) async {
    final mockAppService = MockAppService();
    when(() => mockAppService.getKIsWeb()).thenReturn(false);

    await tester.pumpWidget(
      MaterialApp(
        title: 'Flutter Demo',
        home: Scaffold(
          body: MyWidget(
            appService: mockAppService,
          ),
        ),
      ),
    );

    final webTextFinder = find.text('I\'m not web');
    expect(webTextFinder, findsOneWidget);
  });
}

Please note that I am using Mocktail here instead of Mockito. But you should get the idea.

when(() => mockAppService.getKIsWeb()).thenReturn(false); is Mocktails way to define the mocked behavior. https://pub.dev/packages/mocktail

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文