Files
slogan/test/core/auth/auth_provider_test.dart
T
adminandClaude Opus 4.7 acbe60c13c feat: app 骨架 + 网络层 + 认证(登录/注册)
- flutter create 初始化 + 依赖(riverpod 3/dio/go_router/three_dart 0.0.16)
- ApiClient:JWT 拦截器 + 统一响应解包 + 401 登出回调 + multipart 上传
- TokenStorage(shared_preferences)+ AuthNotifier 登录/登出
- 登录页(含注册对话框)+ 4 Tab 主框架
- 6 个单元测试通过(网络层 4 + 认证 2)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-31 12:39:01 +08:00

79 lines
2.6 KiB
Dart

import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:slogan_app/core/auth/auth_provider.dart';
import 'package:slogan_app/core/network/api_client.dart';
import 'package:slogan_app/core/storage/token_storage.dart';
import '../network/api_client_test.dart';
void main() {
test('登录成功:token 持久化 + 状态 authenticated', () async {
final adapter = MockAdapter();
adapter.onRequest = (o) => Response(
requestOptions: o,
data: {
'code': 0,
'message': 'OK',
'data': {
'token': 'jwt-token',
'user': {'id': 7, 'name': '测试'}
}
});
final storage = InMemoryTokenStorage();
final container = ProviderContainer(overrides: [
tokenStorageProvider.overrideWithValue(storage),
apiClientProvider.overrideWith((ref) => ApiClient(
tokenStorage: storage,
dio: Dio(BaseOptions(baseUrl: 'http://test'))
..httpClientAdapter = adapter)),
]);
addTearDown(container.dispose);
await container.read(authProvider.notifier).login('a', '123456');
final state = container.read(authProvider);
expect(state.value?.authenticated, true);
expect(state.value?.userId, 7);
expect(storage.token, 'jwt-token');
});
test('登录失败:状态 error 携带 message', () async {
final adapter = MockAdapter();
adapter.onRequest = (o) => Response(
requestOptions: o,
data: {'code': 50, 'message': '账号不存在', 'data': null});
final storage = InMemoryTokenStorage();
final container = ProviderContainer(overrides: [
tokenStorageProvider.overrideWithValue(storage),
apiClientProvider.overrideWith((ref) => ApiClient(
tokenStorage: storage,
dio: Dio(BaseOptions(baseUrl: 'http://test'))
..httpClientAdapter = adapter)),
]);
addTearDown(container.dispose);
await container.read(authProvider.notifier).login('a', '123456');
final state = container.read(authProvider);
expect(state.hasError, true);
expect(state.error.toString(), contains('账号不存在'));
expect(state.value?.authenticated, false);
});
}
/// 内存版 TokenStorage(测试用,无需 SharedPreferences 插件)
class InMemoryTokenStorage extends TokenStorage {
String? _t;
@override
String? get token => _t;
@override
Future<void> load() async {}
@override
Future<void> save(String token) async => _t = token;
@override
Future<void> clear() async => _t = null;
}