【问题标题】:Flutter: Test that a specific exception is thrownFlutter:测试是否抛出了特定的异常
【发布时间】:2019-06-11 23:25:27
【问题描述】:

简而言之,在 dart 中进行单元测试时,throwsA(anything) 对我来说是不够的。如何测试特定的错误消息或类型

这是我想捕捉的错误:

class MyCustErr implements Exception {
  String term;

  String errMsg() => 'You have already added a container with the id 
  $term. Duplicates are not allowed';

  MyCustErr({this.term});
}

这是当前通过的断言,但想检查上面的错误类型:

expect(() => operations.lookupOrderDetails(), throwsA(anything));

这就是我想做的:

expect(() => operations.lookupOrderDetails(), throwsA(MyCustErr));

【问题讨论】:

标签: dart flutter flutter-test


【解决方案1】:

这应该做你想做的:

expect(() => operations.lookupOrderDetails(), throwsA(isA<MyCustErr>()));

如果您只想检查异常,请查看answer

【讨论】:

  • 这对我不起作用。可能是由于我的设置:Expected: &lt;Instance of 'MyCustErr'&gt; Actual: &lt;Closure: () =&gt; dynamic&gt; 删除关闭也不起作用
  • nossir 它不适合我,但只要我有替代方案。谢谢!
  • 作为对未来人们的说明,我无法找到第一个工作替代方案。我发现这是因为 VS Code Intellisense 让我在您实际想要导入 'package:matcher/matcher.dart' 时导入 'package:flutter/{widgets-material-cupertino}.dart'
  • TypeMatcher 从 Flutter 1.12.1 开始被弃用。对我来说,这个匹配器有效:throwsA(isInstanceOf&lt;MyCustErr&gt;())
  • TypeMatcherisInstanceOf 均已弃用。请改用throwsA(isA&lt;MyCustErr&gt;())
【解决方案2】:

在 Flutter 1.12.1 中弃用了 `TypeMatcher' 之后,我发现它可以工作:

expect(() => operations.lookupOrderDetails(), throwsA(isInstanceOf<MyCustErr>()));

【讨论】:

  • isInstanceOf 也已被弃用,取而代之的是 isA。所以代码现在应该是expect(() =&gt; operations.lookupOrderDetails(), throwsA(isA&lt;MyCustErr&gt;()));
【解决方案3】:

截至 2021 年 4 月,这是正确的方法。

正确的方法

import 'package:dcli/dcli.dart';
import 'package:test/test.dart';

 /// GOOD: works in all circumstances.
 expect(() => restoreFile(file), throwsA(isA<RestoreFileException>()));

一些例子显示:

方法不正确

import 'package:dcli/dcli.dart';
import 'package:test/test.dart';
 /// BAD: works but not in all circumstances
 expect(restoreFile(file), throwsA(isA<RestoreFileException>()));

注意在期望之后缺少的 '() => '。

不同之处在于,第一种方法适用于返回 void 的函数,而第二种方法则不行。

所以第一种方法应该是首选技术。

测试特定的错误信息:

同时检查异常内容

import 'package:dcli/dcli.dart';
import 'package:test/test.dart';

    expect(
        () => copy(from, to),
        throwsA(predicate((e) =>
            e is CopyException &&
            e.message == 'The from file ${truepath(from)} does not exists.')));

【讨论】:

  • 这当然有效,但没有任何合乎逻辑的理由为什么要通过 lambdas 让它工作!与 JUnit 相比,这是直接不直观的语法。
  • @Arrow 如果被调用的方法返回 null 那么你必须使用 () 否则你会得到一个编译错误:这个表达式的类型是 'void' 所以它的值不能被使用。 ...我确实有 11 个 lints,这可能就是您看到差异的原因。
【解决方案4】:

首先导入正确的包'package:matcher/matcher.dart';

expect(() => yourOperation.yourMethod(),
      throwsA(const TypeMatcher<YourException>()));

【讨论】:

    【解决方案5】:

    如果有人想像我一样使用异步函数进行测试,你需要做的就是在期望中添加 async 关键字,记住 lookupOrderDetails 是一个异步函数:

    expect(() **async** => **await** operations.lookupOrderDetails(), throwsA(const TypeMatcher<MyCustErr>()));
    
    expect(() **async** => **await** operations.lookupOrderDetails(), isInstanceOf<MyCustErr>()));
    

    它仍然使用Gunter的答案,非常好!

    【讨论】:

    • 不知道为什么,但是这些变体都对我不起作用,但是 expect(() async =&gt; await resultFuture, throwsA(isInstanceOf&lt;MyCustErr&gt;())); 确实
    【解决方案6】:

    当前期望函数调用引发异常的正确方法是:

    expect(operations.lookupOrderDetails, throwsA(isA<MyCustErr>()));`
    

    【讨论】:

      猜你喜欢
      • 2021-08-25
      • 2021-02-26
      • 2023-01-25
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-26
      • 1970-01-01
      相关资源
      最近更新 更多