[英]Dart / Flutter Web: How to write a test that covers `kIsWeb == true`?
I want to run a unit test that covers both possible cases, web and non-web deployment.我想运行一个单元测试,涵盖可能的情况,Web 和非 Web 部署。 The code for the class to be tested basically 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");
}
}
}
kIsWeb
is a constant provided by Dart that determines if the application was compiled to run on the web. kIsWeb
是 Dart 提供的一个常量,用于确定应用程序是否编译为在 Web 上运行。
My current test class implementation is only able to test the non-web path.我当前的测试类实现只能测试非 web 路径。 Is there a way to create a test for the case of kIsWeb == true
?有没有办法为kIsWeb == true
的情况创建测试?
I'm not sure if there is a way to test it directly from a StatelessWidget, but I can show you a way that makes use of some concepts of Clean Architecture.我不确定是否有办法直接从 StatelessWidget 测试它,但我可以向您展示一种利用清洁架构的一些概念的方法。 Basically, you want to decouple the UI (that is, your widgets) from pure logic.基本上,您希望将 UI(即您的小部件)与纯逻辑分离。 So, what I usually do is to have a class that handles the logic, like this:所以,我通常做的是有一个处理逻辑的类,如下所示:
class MyWidgetViewModel {
/// Whether or not the current environment is web.
/// Should only be overridden for testing purposes.
/// Otherwise, defaults to [kIsWeb].
@visibleForTesting
bool isWeb = kIsWeb;
}
Here, I have wrapped the kIsWeb
constant in another variable isWeb
, which defaults to kIsWeb.在这里,我将kIsWeb
常量包装在另一个变量isWeb
中,该变量默认为 kIsWeb。 This means that it can be reassigned at a later time and, moreover, it is only visible to test cases thanks to the annotation @visibleForTesting
.这意味着它可以在以后重新分配,而且,由于注释@visibleForTesting
,它只对测试用例可见。
At this point, we can reference that class in the widget.此时,我们可以在小部件中引用该类。 I generally use Dependency Injection with either Provider or BLoC, but here, for the sake of simplicity, I'll just pass the ViewModel in the widget constructor.我通常将依赖注入与 Provider 或 BLoC 一起使用,但在这里,为了简单起见,我将只在小部件构造函数中传递 ViewModel。
class MyWidget extends StatelessWidget {
final MyWidgetViewModel myViewModel;
const MyWidget(this.myViewModel, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
if (myViewModel.isWeb) { //<- Here we use `isWeb` instead of `kIsWeb`
return Text("I'm web");
} else {
return Text("I'm not web");
}
}
}
Finally, we can exploit the isWeb
variable in the tests.最后,我们可以在测试中利用isWeb
变量。 Don't forget to pass an instance of MyWidgetViewModel()
to your MyWidget
during the setup of the variables.不要忘记在设置变量期间将MyWidgetViewModel()
的实例传递给您的MyWidget
。
test(
'Test based on platform (is web or not).',
() async {
// Arrange (setup)
...
final MyWidgetViewModel myViewModel = MyWidgetViewModel();
myViewModel.isWeb = true; //<- Use this to assign the value you prefer
...
// Assert (expect, verify)
...
},
);
You could also add a constructor and attribute to your widget which you would decorate with @visibleForTesting
.您还可以将构造函数和属性添加到您将使用@visibleForTesting
装饰的小部件。 Something similar to:类似于:
class MyWidget extends StatelessWidget {
final bool isTestingForWeb;
MyWidget({@visibleForTesting this.isTestingForWeb = false});
@override
Widget build(BuildContext context) {
if (kIsWeb || isTestingForWeb) {
return Text("I'm web");
} else {
return Text("I'm not web");
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.