繁体   English   中英

如何测试在 Flutter 中作为参数传递的 Function?

[英]How to test Function passed as an argument in Flutter?

提示:本站为国内最大中英文翻译问答网站,提供中英文对照查看,鼠标放在中文字句上可显示英文原文

如何测试在 Flutter 中作为参数传递的 Function?

代码:

Future<User> execute({
    required String username,
    required String password,
    required void Function(AuthFailure fail) onFailure,
    required void Function(User user) onSuccess,
}) async {
    if (username.isNonValid || password.isNonValid) {
      onFailure(const AuthFailure.wrongCredentials()); // I want to test this line
      return const User.anonymous();
    }
    ...
}

测试:

  test('use case - failure execution for incorrect credentials', () async {
    // GIVEN
    // WHEN
    final user = await useCase.execute(
      username: "noname",
      password: "password",
      onFailure: (fail) {},
      onSuccess: (user) {},
    );
    // THEN
    // TODO how to verify onFailure call inside useCase?
    expect(user, const User.anonymous());
  });

或者也许这种测试方式不是惯用的方式,因为测试变得更加白盒而不是黑盒? 我是否应该将传递函数视为 arguments 以将用例用作反模式? 那我可以改变它。 建议是从useCase.execute()返回类似Either的东西:

Future<Either<Failure, Success>> execute({
    required String username,
    required String password,
}) async {
    if (username.isEmpty || password.isEmpty) {
      // return wrapper around AuthFailure.wrongCredentials()) of Either left subtype (Either has two subtypes)
    }
    ...
}

这样我只验证返回类型,所有的行都是这样覆盖的。 它会起作用,但我对最简单而不是最聪明的解决方案感觉更好。

PS 我对 mocking 使用 Mocktail,但也热烈欢迎在解决方案中使用 Mockito。

如果你只是想验证回调是否被触发,我个人会让你的回调设置一个标志然后测试那个标志,我认为这很简单,没有魔法也很容易理解:

test('use case - failure execution for incorrect credentials', () async {
  var failureCalled = false;

  final user = await useCase.execute(
    username: "noname",
    password: "password",
    onFailure: (fail) => failureCalled = true,
    onSuccess: (user) {},
  );

  expect(user, const User.anonymous());
  expect(failureCalled, true);
});

但是如果你真的想使用Mock s,你将需要一些Mock object 来使用和调用回调中的实例方法。 使用 Mockito 你可以这样做:

test('use case - failure execution for incorrect credentials', () async {
  dynamic mock = Mock();

  final user = await useCase.execute(
    username: "noname",
    password: "password",
    onFailure: (fail) => mock.fail(fail),
    onSuccess: (user) {},
  );

  expect(user, const User.anonymous());
  verify(mock.fail(any)).called(1);
});

一些注意事项:

  • 为避免使用预期的实例方法声明 class 然后生成代码存根,请创建一个原始Mock实例但将其声明为dynamic以禁用 static 类型检查。 这将利用Mock.noSuchMethod实现。
  • 您不能直接使用onFailure: mock.fail ,因为Mock没有生成存根,并且mock.fail将只是null而不是Function

我没有使用 Mocktail 的经验,但我想你可以做类似的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2023 STACKOOM.COM