【问题标题】:failed `assert` does not throw `AssertionError` in dart with null-safety, any workaround?失败的`assert`不会在具有空安全性的dart中抛出`AssertionError`,有什么解决方法吗?
【发布时间】:2021-03-04 07:56:03
【问题描述】:

当我开始转换到null-safety
我遇到了这个问题:
运行下面的测试

//  ignore_for_file: avoid_catching_errors

import 'package:test/test.dart';

void main() {
  test(
      'WHEN `AssertionError` is thrown '
      'THEN `Error` is `AssertionError`'
      '', () {
    Type? type;

    void fun() => throw AssertionError();

    try {
      fun();
    } on Error catch (e) {
      if (e is AssertionError) {
        type = e.runtimeType;
      }
    }

    expect(type, AssertionError);
  });
  test('WHEN `assertion` fails THEN throw `AssertionError`', () {
    Type? type;

    void fun() {
      assert(false);
    }

    try {
      fun();
    } on Error catch (e) {
      if (e is AssertionError) {
        type = e.runtimeType;
      }
    }

    expect(type, AssertionError);
  });

  test('WHEN `assertion fails THEN throwsA(AssertionError) should be true', () {
    bool fun() {
      assert(false);
      return true;
    }

    expect(fun, throwsA(isA<AssertionError>()));
  });
}

输出以下日志

00:00 +0: loading test/widget_test.dart                                                                                                                                                                
00:01 +0: loading test/widget_test.dart                                                                                                                                                                
00:01 +0: test/widget_test.dart: WHEN `AssertionError` is thrown THEN `Error` is `AssertionError`                                                                                                      
00:01 +1: test/widget_test.dart: WHEN `AssertionError` is thrown THEN `Error` is `AssertionError`                                                                                                      
00:01 +1: test/widget_test.dart: WHEN `assertion` fails THEN throw `AssertionError`                                                                                                                    
00:01 +1 -1: test/widget_test.dart: WHEN `assertion` fails THEN throw `AssertionError` [E]                                                                                                             
  Expected: Type:<AssertionError>
    Actual: Type:<_AssertionError>

  package:test_api            expect
  test/widget_test.dart 39:5  main.<fn>


00:01 +1 -1: test/widget_test.dart: WHEN `assertion fails THEN throwsA(AssertionError) should be true                                                                                                  
00:01 +2 -1: test/widget_test.dart: WHEN `assertion fails THEN throwsA(AssertionError) should be true                                                                                                  
00:01 +2 -1: Some tests failed.                                                                                                                                                                        
pub failed (1; 00:01 +2 -1: Some tests failed.
)

请注意,尝试使用 _AssertionError 会输出错误

名称“_AssertionError”未定义,因此不能用于 '是'的表达。尝试将名称更改为现有名称 类型,或创建一个名为“_AssertionError”的类型。


请不要回复you are not supposed to catch errors
下面的代码纯粹是示范性的
我在编写测试时遇到了问题 而期望(乐趣(),抛出A(AssertionError));已包含在代码示例中,它不适合我的用例


这不是错误,而是预期的行为,请参阅issue 45191

你不应该期望assert(false) 抛出一个运行时类型为AssertionError 的对象,它只能保证抛出一个可类型化的对象(即运行时类型为AssertionError 的子类型),这可能是测试 expect(type, AssertionError); 失败的原因。


下面是我的医生和我的 pubspec

[✓] Flutter (Channel master, 2.1.0-11.0.pre.97, on Linux, locale en_US.UTF-8)
    • Flutter version 2.1.0-11.0.pre.97 at /home/francesco/snap/flutter/common/flutter
    • Framework revision c14c8d8177 (2 hours ago), 2021-03-03 21:40:34 -0800
    • Engine revision 72bbc5d92c
    • Dart version 2.13.0 (build 2.13.0-93.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.2)
    • Android SDK at /home/francesco/Android/Sdk
    • Platform android-30, build-tools 30.0.2
    • ANDROID_SDK_ROOT = /home/francesco/Android/Sdk
    • Java binary at: /usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_282-8u282-b08-0ubuntu1~20.04-b08)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • CHROME_EXECUTABLE = /snap/bin/chromium

[✓] Linux toolchain - develop for Linux desktop
    • clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
    • cmake version 3.10.2
    • ninja version 1.8.2
    • pkg-config version 0.29.1

[!] Android Studio (not installed)
    • Android Studio not found; download from https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/linux#android-setup for detailed instructions).

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Linux
    • Chrome (web)    • chrome • web-javascript • Chromium 89.0.4389.72 snap

! Doctor found issues in 1 category.
francesco@francesco-yoga720:~/project
name: issue
description: A new Flutter project.
version: 1.0.0+1

environment:
  sdk: '>=2.12.0 <3.0.0'

dev_dependencies:
  test: ^1.16.5

【问题讨论】:

  • 你为什么不用throwsA Matcher 来代替呢? (expect(fun, throwsA(isA&lt;AssertionError&gt;()));) 或者,如果您更喜欢使用自己的手册 try-catch,则改为设置布尔标志。
  • 好点,谢谢...但它也失败了...更新问题
  • 失败是因为你没有正确使用throwsAMatcher。请阅读它的文档(以及我在评论中建议的代码)。
  • 要明确:throwsAFunction 匹配;这意味着fun,而不是fun()。你不能调用你的函数,因为那样它会抛出一个异常并展开调用堆栈Matcher做任何事情之前。
  • 仅供参考,根据您的最新编辑,使用throwsA 的测试成功。

标签: flutter dart testing error-handling dart-null-safety


【解决方案1】:

你不应该期望assert(false) 抛出一个运行时类型为AssertionError 的对象,它只能保证抛出一个可类型化的对象(即运行时类型为AssertionError 的子类型),这可能是测试 expect(type, AssertionError); 失败的原因。

【讨论】:

  • 我最终为我的特定用例创建了一个扩展 AssertionError 的自定义错误和一个模拟 assert 的函数,感谢您的洞察力:)
猜你喜欢
  • 2012-02-28
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2020-05-20
相关资源
最近更新 更多