修复用户端令牌失效后的登录恢复

This commit is contained in:
czl231
2026-09-04 21:54:35 +08:00
parent 7cc56f955f
commit e092659622
19 changed files with 636 additions and 33 deletions

View File

@@ -1,5 +1,5 @@
// 功能描述:验证受保护头像二进制接口的鉴权读取和异常处理。
// 版本1.1.0
// 功能描述:验证统一请求鉴权、会话失效通知和二进制资源处理。
// 版本1.2.0
import 'dart:typed_data';
import 'package:flutter_test/flutter_test.dart';
@@ -51,4 +51,99 @@ void main() {
),
);
});
test('受保护接口返回 HTTP 401 时通知会话并抛出专用异常', () async {
final rejectedTokens = <String>[];
final client = ApiClient(
() => 'JWT expired-token',
baseUrl: 'https://api.example.com',
onUnauthorized: rejectedTokens.add,
client: MockClient((request) async => http.Response('', 401)),
);
await expectLater(
client.get('/protected'),
throwsA(isA<SessionExpiredException>()),
);
expect(rejectedTokens, ['JWT expired-token']);
});
test('受保护接口返回鉴权业务码时通知会话', () async {
final rejectedTokens = <String>[];
final client = ApiClient(
() => 'JWT expired-token',
baseUrl: 'https://api.example.com',
onUnauthorized: rejectedTokens.add,
client: MockClient(
(request) async => http.Response(
'{"code":1308,"message":"Token Expired","details":null}',
200,
),
),
);
await expectLater(
client.get('/protected'),
throwsA(isA<SessionExpiredException>()),
);
expect(rejectedTokens, ['JWT expired-token']);
});
test('未鉴权接口返回 401 时不得清理已有会话', () async {
final rejectedTokens = <String>[];
final client = ApiClient(
() => 'JWT current-token',
baseUrl: 'https://api.example.com',
onUnauthorized: rejectedTokens.add,
client: MockClient((request) async => http.Response('', 401)),
);
await expectLater(
client.post('/login', authenticated: false),
throwsA(
isA<ApiException>()
.having((error) => error.code, 'code', 401)
.having((error) => error is SessionExpiredException, 'session expired', isFalse),
),
);
expect(rejectedTokens, isEmpty);
});
test('头像接口返回 401 时同样触发统一会话失效', () async {
final rejectedTokens = <String>[];
final client = ApiClient(
() => 'JWT expired-token',
baseUrl: 'https://api.example.com',
onUnauthorized: rejectedTokens.add,
client: MockClient((request) async => http.Response('', 401)),
);
await expectLater(
client.getBytes('/avatar'),
throwsA(isA<SessionExpiredException>()),
);
expect(rejectedTokens, ['JWT expired-token']);
});
test('头像接口在 HTTP 200 错误体中返回鉴权码时触发会话失效', () async {
final rejectedTokens = <String>[];
final client = ApiClient(
() => 'JWT expired-token',
baseUrl: 'https://api.example.com',
onUnauthorized: rejectedTokens.add,
client: MockClient(
(request) async => http.Response(
'{"code":1715,"message":"Unauthorized","details":null}',
200,
headers: {'content-type': 'application/json'},
),
),
);
await expectLater(
client.getBytes('/avatar'),
throwsA(isA<SessionExpiredException>()),
);
expect(rejectedTokens, ['JWT expired-token']);
});
}