Flutter测试框架插件angel3_test的使用
Flutter测试框架插件angel3_test的使用
angel3_test
是一个用于 Angel3 框架的测试工具库。通过该库,你可以方便地编写和运行测试用例,确保你的应用在不同情况下都能正常工作。
TestClient
TestClient
类是一个自定义的 angel3_client
,它可以向你的服务器发送模拟请求。这意味着你无需将服务器绑定到 HTTP 即可运行测试。此外,它支持服务和其他功能。TestClient
还支持 WebSocket。WebSocket 在此库中无法模拟(目前),因此调用 websocket()
函数会将你的服务器绑定到 HTTP(如果尚未监听)。返回值是一个 WebSockets
客户端实例(来自 package:angel3_websocket
)。
var ws = await client.websocket('/ws');
ws.service('api/users').onCreated.listen(...);
// 接收 WebSocket 上发送的所有数据块:
ws.onData.listen(...);
Matchers
该包包含多个 Matcher
,它们可以应用于任何 package:http
的 Response
,而不仅仅是那些由 Angel 返回的响应。
void test('foo', () async {
var res = await client.get('/foo');
expect(res, allOf([
isJson({'foo': 'bar'}), // 响应体是 JSON 并且内容为 {"foo": "bar"}
hasStatus(200), // 状态码为 200
hasContentType(ContentType.JSON), // 内容类型为 JSON
hasContentType('application/json'), // 内容类型为 application/json
hasHeader('server'), // 存在 server 头
hasHeader('server', 'angel'), // server 头的值为 angel
hasHeader('foo', ['bar', 'baz']), // foo 头的值为 bar 或 baz
hasBody(), // 响应体不为空
hasBody('{"foo":"bar"}') // 响应体为 {"foo":"bar"}
]));
});
void test('error', () async {
var res = await client.get('/error');
expect(res, isAngelHttpException()); // 响应是 AngelHttpException
expect(res, isAngelHttpException(statusCode: 404, message: ..., errors: [...])) // 可选参数
});
hasValidBody
是此库中最强大的 Matcher
之一,因为它允许你根据验证模式验证 JSON 响应体。Angel3 提供了一个综合的验证库,与你已经使用的 matcher
包紧密集成。
test('validate response', () async {
var res = await client.get('/bar');
expect(res, hasValidBody(Validator({
'foo': isBoolean,
'bar': [isString, equals('baz')],
'age*': [],
'nested': someNestedValidator
})));
});
完整示例
以下是一个完整的示例,展示了如何使用 angel3_test
来测试一个简单的 Angel3 应用程序。
import 'dart:io';
import 'package:angel3_framework/angel3_framework.dart';
import 'package:angel3_test/angel3_test.dart';
import 'package:angel3_validate/angel3_validate.dart';
import 'package:angel3_websocket/server.dart';
import 'package:test/test.dart';
void main() {
Angel app;
late TestClient client;
setUp(() async {
app = Angel()
..get('/hello', (req, res) => 'Hello')
..get(
'/error',
(req, res) =>
throw AngelHttpException.forbidden(message: 'Test')
..errors.addAll(['foo', 'bar']))
..get('/body', (req, res) {
res
..write('OK')
..close();
})
..get(
'/valid',
(req, res) =>
{
'michael': 'jackson',
'billie': {'jean': 'hee-hee', 'is_my_lover': false}
})
..post('/hello', (req, res) async {
var body = await req.parseBody().then((_) => req.bodyAsMap);
return {'bar': body['foo']};
})
..get('/gzip', (req, res) async {
res
..headers['content-encoding'] = 'gzip'
..add(gzip.encode('Poop'.codeUnits));
await res.close();
})
..use(
'/foo',
AnonymousService(
index: ([params]) async => [
{'michael': 'jackson'}
],
create: (dynamic data, [params]) async => {'foo': 'bar'}));
var ws = AngelWebSocket(app);
await app.configure(ws.configureServer);
app.all('/ws', ws.handleRequest);
app.errorHandler = (e, req, res) => e.toJson();
client = await connectTo(app);
});
tearDown(() async {
await client.close();
});
group('matchers', () {
group('isJson+hasStatus', () {
test('get', () async {
final response = await client.get(Uri.parse('/hello'));
expect(response, isJson('Hello'));
});
test('post', () async {
final response =
await client.post(Uri.parse('/hello'), body: {'foo': 'baz'});
expect(response, allOf(hasStatus(200), isJson({'bar': 'baz'})));
});
});
test('isAngelHttpException', () async {
var res = await client.get(Uri.parse('/error'));
print(res.body);
expect(res, isAngelHttpException());
expect(
res,
isAngelHttpException(
statusCode: 403, message: 'Test', errors: ['foo', 'bar']));
});
test('hasBody', () async {
var res = await client.get(Uri.parse('/body'));
expect(res, hasBody());
expect(res, hasBody('OK'));
});
test('hasHeader', () async {
var res = await client.get(Uri.parse('/hello'));
expect(res, hasHeader('server'));
expect(res, hasHeader('server', 'angel'));
expect(res, hasHeader('server', ['angel']));
});
test('hasValidBody+hasContentType', () async {
var res = await client.get(Uri.parse('/valid'));
expect(res, hasContentType('application/json'));
expect(
res,
hasValidBody(Validator({
'michael*': [isString, isNotEmpty, equals('jackson')],
'billie': Validator({
'jean': [isString, isNotEmpty],
'is_my_lover': [isBool, isFalse]
})
})));
});
test('gzip decode', () async {
var res = await client.get(Uri.parse('/gzip'));
expect(res, hasHeader('content-encoding', 'gzip'));
expect(res, hasBody('Poop'));
});
group('service', () {
test('index', () async {
var foo = client.service('foo');
var result = await foo.index();
expect(result, [
{'michael': 'jackson'}
]);
});
test('create', () async {
var foo = client.service('foo');
var result = await foo.create({});
expect(result, {'foo': 'bar'});
});
});
test('websocket', () async {
var ws = await client.websocket();
var foo = ws.service('foo');
await foo.create({});
var result = await foo.onCreated.first;
expect(result.data, equals({'foo': 'bar'}));
});
});
}
更多关于Flutter测试框架插件angel3_test的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter测试框架插件angel3_test的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,angel3_test
是一个用于 Dart 和 Flutter 应用的测试框架插件,它基于 Angel 框架的测试工具。尽管 angel3_test
主要用于后端服务测试,但你也可以在 Flutter 应用中对相关的 Dart 代码进行单元测试。以下是一个简单的示例,展示如何在 Flutter 项目中使用 angel3_test
进行测试。
首先,确保你已经在 pubspec.yaml
文件中添加了 angel3_test
依赖:
dependencies:
flutter:
sdk: flutter
# 其他依赖...
dev_dependencies:
test: ^1.16.0
angel3_test: ^x.y.z # 请替换为最新版本号
然后,运行 flutter pub get
以获取依赖。
接下来,创建一个测试文件,例如 test/example_test.dart
。在这个文件中,我们将编写一个简单的测试来演示如何使用 angel3_test
。
import 'package:test/test.dart';
import 'package:angel3_test/angel3_test.dart';
import 'package:angel3_framework/angel3_framework.dart';
void main() {
group('Angel App Tests', () {
late Angel app;
setUp(() async {
app = Angel();
// 注册一些简单的路由用于测试
app.get('/hello', (req, res) async {
res.write('Hello, World!');
});
// 初始化应用(如果有必要)
await app.configure(server);
});
tearDown(() async {
// 清理资源
await app.close();
});
test('GET /hello returns Hello, World!', () async {
var response = await request(app).get('/hello');
expect(response.statusCode, equals(200));
expect(response.body, equals('Hello, World!'));
});
// 你可以添加更多的测试用例
// test('POST /example does something', () async { ... });
});
}
在这个示例中,我们做了以下几件事:
- 引入必要的包:
test
和angel3_test
。 - 创建测试组:使用
group
函数来组织相关的测试用例。 - 设置和清理:使用
setUp
和tearDown
函数在每个测试用例之前和之后进行初始化和清理工作。 - 编写测试用例:使用
test
函数定义一个具体的测试用例,通过request(app).get('/hello')
发送 GET 请求到/hello
路由,并验证响应的状态码和响应体。
请注意,server
在 app.configure(server);
中被引用,但在上述示例中并未定义。在完整的后端应用中,你可能会初始化一个 HTTP 服务器实例并将其传递给 app.configure
。然而,在 Flutter 测试环境中,通常不需要这样做,因为 angel3_test
提供了模拟请求和响应的工具。如果你只是测试路由处理逻辑,可以忽略 app.configure(server);
这一行。
此外,由于 Flutter 主要用于前端开发,而后端服务测试通常不在 Flutter 测试套件中进行,因此在实际 Flutter 应用中,你可能会更倾向于使用 http
包或其他网络请求库来模拟后端请求,并使用 test
包进行单元测试。angel3_test
更适合在纯 Dart 后端服务或包含 Dart 后端服务的 Flutter 应用的后端部分进行测试。