如何使用mocktail测试小部件方法

问题描述 投票:0回答:1

我正在尝试测试小部件的方法是否确实被调用,但我似乎无法正确执行。

我的小部件看起来像这样:

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

  final Function(DataModel dataModel) callSaveData;

  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  DataModel dataModel;
  ...
  @override
  Widget build(BuildContext context) {
    ...
    return ElevatedButton(
      onPressed: () {
        widget.callSaveData(someStateData);
      },
      child: Text('Hello'),
    )
  }
}

我的测试是这样的:

class MockCallSaveData extends Mock {
  void call(DataModel mockDataModel);
}

void main() {
  late Function(DataModel mockDataModel)
      mockCallSaveData;
  group('Tests', () {
    setUp(() {
      mockCallSaveData = MockCallSaveData();
    });
    Future<void> _buildScreen(WidgetTester tester) async {
      return tester.pumpWidget(
        ...
        return MyWidget(
          callSaveData: mockCallSaveData,
        );
      );
    }
    testWidgets('Test widget', (WidgetTester tester) async {
      when(() => mockCallSaveData(mockDataModel))
          .thenAnswer((_) => null);
      await _buildScreen(tester);
      await tester.pumpAndSettle();
      ... interact with UI, tap the button that triggers the callback ...
      verify(
        () => mockCallSaveData(mockDataModel),
      );
    });
  });
}

但我不断收到以下错误

The following TestFailure was thrown running a test:
No matching calls. All calls: MockCallSaveData.call(mockDataModel(null, test_city,
null, [email protected], test_firstName, test_last_name, H123, null, null, 1, 1135, +41 79 123 34 56,
test_street, test_username, 1234, null, null, null))
(If you called `verify(...).called(0);`, please instead use `verifyNever(...);`.)

因此,看起来模拟已被调用,并且具有正确的数据。 “mockCallSaveData”实例应该是相同的,它在 setUp() 中实例化,传递给测试,同时在 testWidgets() 中引用。

任何帮助将不胜感激,我花了几个小时试图让它发挥作用。

flutter unit-testing instance
1个回答
0
投票

修复了它,感谢@jamesdlin 的提示。 我没有注意到传递给

DataModel
widget.callSaveData(someStateData);
实例正在被操纵。

就在该调用之前,有一个实用程序方法执行如下操作:

void textChanged({
    String? zip,
    String? street,
    ... etc etc
  }) {
    userViewModel = DataModel(
      zip: zip ?? dataModel!.zip,
      street: street ?? dataModel!.street,
      ... etc
    );
  }

这当然导致了新实例的交付。 现在,我所做的就是解决这个问题,并使代码总体上更好一点,就是向我的

DataModel
类添加一个 copyWith 方法。

class DataModel extends Equatable {
  DataModel({this.zip, this.street, ... etc});
  String? zip;
  String? city;

  DataModel copyWith({String? zip, String? city}) {
    return DataModel(
      zip: zip ?? this.zip,
      city: city ?? this.city,
    );
  }
}

这允许我按如下方式测试我的小部件:

testWidgets('Test widget', (WidgetTester tester) async {
      const String test_zip = 'test_zip';
      when(() => mockCallSaveData(mockDataModel))
          .thenAnswer((_) => null);
      await _buildScreen(tester);
      await tester.pumpAndSettle();
      ... interact with UI, tap the button that triggers the callback ...
      verify(
        () => mockCallSaveData(mockDataModel.copyWith(zip: test_zip)),
      );
    });

现在一切正常。

© www.soinside.com 2019 - 2024. All rights reserved.