我想运行一个单元测试,它涵盖了可能的情况,web和非web部署。要测试的类的代码基本上如下所示:
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
if (kIsWeb) {
return Text("I'm web");
} else {
return Text("I'm not web");
}
}
}
kIsWeb
是Dart提供的一个常量,用于确定应用程序是否编译为在web上运行。
我当前的测试类实现只能测试非web路径。有没有办法为kIsWeb == true
的情况创建一个测试?
试着这样运行测试:
颤振测试——平台铬
很遗憾,此方法可能在某些平台上不起作用(Windows 10的问题(Flutter for web仍在BETA中。
更多信息请点击此处。
我不确定是否有一种方法可以直接从StatelessWidget测试它,但我可以向您展示一种使用Clean Architecture的一些概念的方法。基本上,您希望将UI(即小部件(与纯逻辑解耦。所以,我通常要做的是有一个处理逻辑的类,比如:
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;
}
在这里,我已经将kIsWeb
常量封装在另一个变量isWeb
中,该变量默认为kIsWeb。这意味着它可以在以后重新分配,而且,由于注释@visibleForTesting
,它只对测试用例可见。
此时,我们可以在小部件中引用该类。我通常将依赖注入与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");
}
}
}
最后,我们可以在测试中利用isWeb
变量。在设置变量期间,不要忘记将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)
...
},
);
您还可以向小部件添加一个构造函数和属性,用@visibleForTesting
进行装饰。类似于:
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");
}
}
}