小部件测试不会触发 DropdownButton onChanged

Widget Test Doesn't Fire DropdownButton onChanged

我有一个小部件测试,可以点击 DropdownButton 中的一个项目。这应该触发 onChanged 回调,但它没有。这是测试代码。模拟是 Mockito。


void main() {
  //Use a dummy instead of the fake. The fake does too much stuff
  final mockServiceClient = MockTheServiceClient();

  final apiClient = GrpcApiClient(client: mockServiceClient);

  when(mockServiceClient.logEvent(any))
      .thenAnswer((_) => MockResponseFuture(LogEventResponse()));

  testWidgets("select asset type", (tester) async {
    //sets the screen size
    tester.binding.window.physicalSizeTestValue = const Size(3840, 2160);

    // resets the screen to its orinal size after the test end
    addTearDown(tester.binding.window.clearPhysicalSizeTestValue);

    await tester.pumpWidget(AssetApp(apiClient), const Duration(seconds: 5));

    //Construct key with '{DDLKey}_{Id}'
    await tester
        .tap(find.byKey(ValueKey("${assetTypeDropDownKey.value}_PUMP")));

    await tester.pumpAndSettle(const Duration(seconds: 5));

    verify(mockServiceClient.logEvent(any)).called(1);
  });
}

这是小部件的构建方法:

  @override
  Widget build(BuildContext context) {
    return DropdownButton<DropDownItemDefinition>(
      underline: Container(),
      dropdownColor: Theme.of(context).cardColor,
      hint: Text(
        hintText,
        style: Theme.of(context).textTheme.button,
      ),
      //TODO: Use the theme here
      icon: Icon(
        Icons.arrow_drop_down,
        color: Theme.of(context).dividerColor,
      ),
      value: getValue(),
      onChanged: (ddd) {
        setState(() {
          onValueChanged(ddd!);
        });
      },
      items: itemss.map<DropdownMenuItem<DropDownItemDefinition>>((value) {
        return DropdownMenuItem<DropDownItemDefinition>(
          key: ValueKey(
              "${(key is ValueKey) ? (key as ValueKey?)?.value.toString() :
               ''}_${value.id}"),
          value: value,
          child: Tooltip(
              message: value.toolTipText,
              child: Container(
                  margin: dropdownPadding,
                  child: Text(value.displayText,
                      style: Theme.of(context).textTheme.headline3))),
        );
      }).toList(),
    );
  }

请注意,onValueChanged 函数调用了 logEvent 调用。 onChanged 回调永远不会发生,测试失败。这是它应该触发的代码。

  Future onAssetTypeChange(DropDownItemDefinition newValue) async {
    await assetApiClient.logChange(record.id, newValue, DateTime.now());
  }

为什么回调永远不会触发?

注意:我做了另一个小部件测试,Mock 确实验证了客户端是否被正确调用。我认为回调作为小部件测试的一部分存在一些问题。

您需要先指示驱动程序点击 DropdownButton 本身,然后在下拉弹出窗口出现后,点击 DropdownMenuItem。

如果下拉菜单本身不在屏幕上 active/painted,则驱动程序无法从下拉菜单中找到 DropdownMenuItem。