Flutter断言与接口交互插件libasserest_interface的使用

Flutter断言与接口交互插件libasserest_interface的使用

标准接口实现

libasserest_interface 提供了一个标准接口来构建断言处理器。这特别适用于那些希望使用自定义协议的专有协议。

目标与现有方法对比

这一节主要面向开发者,他们决定从零开始实现。如果你已经有了第三方实现,请直接参考“执行”部分。

实现步骤

要实现带有自定义协议的断言,你需要在集成 Asserest 之前创建至少两个对象。

定义属性

首先,准备一个实现了 AsserestProperty 的类,用于指定将要使用的属性。

AsserestProperty 已经提供了四个默认属性,这些属性必须用 final 关键字而不是 getter 来声明。

正确做法

final class CustomProperty implements AsserestProperty {
  [@override](/user/override)
  final Uri url;

  [@override](/user/override)
  final bool accessible;

  [@override](/user/override)
  final Duration timeout;

  [@override](/user/override)
  final int? tryCount;

  // 您自己的属性
}

错误做法

final class CustomProperty implements AsserestProperty {
  [@override](/user/override)
  Uri get url;

  [@override](/user/override)
  bool get accessible;

  [@override](/user/override)
  Duration get timeout;

  [@override](/user/override)
  int? get tryCount;

  // 您自己的属性
}
创建解析属性处理器(可选)

一旦你的属性完成,如果你希望用户通过 Dart 的 map 解析断言信息,你可能需要创建一个基于 PropertyParseProcessor 的解析器。所有预定义的属性将被转换为 Dart 中对应的数据类型,并且包含非标准化属性的不可修改映射。

需要重写的方法或获取器有两个:createProperty 用于将映射值解析为实际的属性对象,supportedSchemes 是一个字符串集,指定支持的协议。

final class CustomPropertyParseProcessor
    extends PropertyParseProcessor<CustomProperty> {
  const CustomPropertyParseProcessor();

  [@override](/user/override)
  CustomProperty createProperty(
      Uri url,
      Duration timeout,
      bool accessible,
      int? tryCount,
      UnmodifiableMapView<String, dynamic> additionalProperty) {
    // 创建 CustomProperty 对象
    return CustomProperty(url, accessible, timeout, tryCount);
  }

  [@override](/user/override)
  Set<String> get supportedSchemes => const {"foo"};
}
测试平台

然后,当解析器准备好使用时,你可以通过扩展 AsserestTestPlatform 来实现测试表单。

它主要重写了 runTestProcess 方法,该方法对应于执行测试并生成给定 URL 的断言结果。

final class CustomTestPlatform extends AsserestTestPlatform<CustomProperty> {
  CustomTestPlatform(super.property);

  [@override](/user/override)
  AsyncTask<CustomProperty, AsserestReport> instantiate(
          CustomProperty parameters,
          [Map<String, SharedData>? sharedData]) =>
      CustomTestPlatform(property);

  [@override](/user/override)
  Future<AsserestResult> runTestProcess() async {
    // 执行测试
    return AsserestResult.success;
  }
}

执行

当测试器准备好使用时,在执行断言之前需要进行一些前置步骤。

与管理器关联

一旦你已经实现了测试器,它必须注册到 AsserestTestAssigner 中,以便在给定测试器时应用测试器,特别是在进行并行测试时。

另外,你可以选择将你自己的解析处理器注册到 AsserestPropertyParser 中,这样它会根据 URL 方案生成相应的属性类型。

AsserestPropertyParser().define(CustomPropertyParseProcessor());
AsserestTestAssigner().assign(
    CustomProperty,
    (property) => CustomTestPlatform(property as CustomProperty));

如果计划使用第三方实现,请也按上述方式附加解析器和测试器,除非开发人员另有说明。

进行测试

每个测试器的属性将相应地生成一个 AsserestReport,其中包含断言结果、URL 访问预期、实际结果(仅表示为 successfailureerror)以及如果启用了计数功能,则包含执行测试所花费的时间。

AsserestParallelTestPlatform 是一个处理多个测试属性并准备在 AsserestParallelExecutor 中生成测试器的类,这是一个并发执行测试器的容器,测试完成后报告将以流的形式出现。

final testPlatform = AsserestParallelTestPlatform();

testPlatform.applyAll([
  // 将要分配给测试的属性
]);

final executor = testPlatform.buildExecutor(
    // 可选偏好设置
    name: "Sample test",
    thread: 6, // 默认使用单线程
    logger: null
);

你可以使用 for 循环或附加 StreamSubscription 来处理流,并且不要忘记在流完成后调用 shutdown 方法:

使用 for 循环

await for (AsserestReport report in executor.invoke()) {
  // 在这里执行任务
}

await executor.shutdown();

使用 StreamSubscription

void reportHandler(AsserestReport report) {
  // 在这里执行任务
}

final Stream<AsserestReport> sr = executor.invoke();
sr.listen(reportHandler)
  ..onDone(() async {
    await executor.shutdown();
  })
  ..onError((err) async {
    await executor.shutdown();
  });

许可证

AGPL-3


以下是完整的示例代码:

import 'dart:collection';

import 'package:async_task/src/async_task_base.dart';
import 'package:async_task/src/async_task_shared_data.dart';
import 'package:libasserest_interface/interface.dart';

final class CustomProperty implements AsserestProperty {
  [@override](/user/override)
  final Uri url;

  [@override](/user/override)
  final bool accessible;

  [@override](/user/override)
  final Duration timeout;

  [@override](/user/override)
  final int? tryCount;

  const CustomProperty(this.url, this.accessible, this.timeout, [this.tryCount]);
}

final class CustomPropertyParseProcessor
    extends PropertyParseProcessor<CustomProperty> {
  const CustomPropertyParseProcessor();

  [@override](/user/override)
  CustomProperty createProperty(
      Uri url,
      Duration timeout,
      bool accessible,
      int? tryCount,
      UnmodifiableMapView<String, dynamic> additionalProperty) {
    return CustomProperty(url, accessible, timeout, tryCount);
  }

  [@override](/user/override)
  Set<String> get supportedSchemes => const {"foo"};
}

final class CustomTestPlatform extends AsserestTestPlatform<CustomProperty> {
  CustomTestPlatform(super.property);

  [@override](/user/override)
  AsyncTask<CustomProperty, AsserestReport> instantiate(
          CustomProperty parameters,
          [Map<String, SharedData>? sharedData]) =>
      CustomTestPlatform(property);

  [@override](/user/override)
  Future<AsserestResult> runTestProcess() async {
    // 运行测试
    return AsserestResult.success;
  }
}

void parallelTestListener(AsserestReport report) {
  // 处理报告
}

void main() async {
  AsserestTestAssigner()
    ..assign(CustomProperty,
        (property) => CustomTestPlatform(property as CustomProperty));

  final parallelTester = AsserestParallelTestPlatform();
  parallelTester.applyAll([
    CustomProperty(Uri.parse("foo://example.com"), true, Duration(seconds: 15)),
    CustomProperty(Uri.parse("foo://bar.com"), true, Duration(seconds: 15), 7),
    CustomProperty(Uri.parse("foo://a.com"), false, Duration(seconds: 15))
  ]);

  final executor = parallelTester.buildExecutor();
  executor.invoke().listen(parallelTestListener)
    ..onDone(() async {
      await executor.shutdown();
    })
    ..onError((err) async {
      await executor.shutdown();
    });
}

更多关于Flutter断言与接口交互插件libasserest_interface的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter断言与接口交互插件libasserest_interface的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中,断言(Assertions)是一种用于调试的工具,用于在代码中检查某些条件是否为真。如果条件为假,断言会抛出一个异常,帮助开发者快速定位问题。而 libasserest_interface 是一个假设的插件,用于与接口进行交互。下面我们将结合断言和 libasserest_interface 来展示如何在Flutter中使用它们。

1. 引入 libasserest_interface 插件

首先,你需要在 pubspec.yaml 文件中添加 libasserest_interface 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  libasserest_interface: ^1.0.0  # 假设的版本号

然后运行 flutter pub get 来获取依赖。

2. 使用断言进行调试

断言通常用于调试阶段,确保代码在特定条件下正确运行。例如:

void fetchData() {
  final url = 'https://api.example.com/data';
  
  // 断言:确保URL不为空
  assert(url != null && url.isNotEmpty, 'URL must not be empty');
  
  // 使用libasserest_interface插件进行接口调用
  libasserest_interface.get(url).then((response) {
    // 处理响应数据
    print('Response: $response');
  }).catchError((error) {
    // 处理错误
    print('Error: $error');
  });
}

在这个例子中,assert 语句用于确保 url 不为空且非空字符串。如果 url 为空,断言将抛出一个异常,并显示错误信息 'URL must not be empty'

3. 使用 libasserest_interface 进行接口交互

假设 libasserest_interface 插件提供了一个简单的 get 方法来发起HTTP GET请求。你可以使用它来与接口进行交互:

import 'package:libasserest_interface/libasserest_interface.dart';

void fetchData() async {
  final url = 'https://api.example.com/data';
  
  // 断言:确保URL不为空
  assert(url != null && url.isNotEmpty, 'URL must not be empty');
  
  try {
    final response = await libasserest_interface.get(url);
    // 处理响应数据
    print('Response: $response');
  } catch (error) {
    // 处理错误
    print('Error: $error');
  }
}

在这个例子中,我们使用 await 来等待异步请求完成,并使用 try-catch 来捕获和处理可能出现的错误。

4. 在Flutter应用中使用

你可以将 fetchData 函数集成到Flutter应用的某个按钮点击事件中,例如:

import 'package:flutter/material.dart';
import 'package:libasserest_interface/libasserest_interface.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Asserts & Interface Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: fetchData,
            child: Text('Fetch Data'),
          ),
        ),
      ),
    );
  }
}

void fetchData() async {
  final url = 'https://api.example.com/data';
  
  // 断言:确保URL不为空
  assert(url != null && url.isNotEmpty, 'URL must not be empty');
  
  try {
    final response = await libasserest_interface.get(url);
    // 处理响应数据
    print('Response: $response');
  } catch (error) {
    // 处理错误
    print('Error: $error');
  }
}
回到顶部