flutter架 构项目基础

This commit is contained in:
崔宝新
2026-09-04 15:22:20 +08:00
parent 70967229d0
commit 0c5aee59c0
265 changed files with 35484 additions and 0 deletions
+128
View File
@@ -0,0 +1,128 @@
// 单元测试:UserModel 的 JSON 解析兼容点
//
// 为什么测它:CurrentUserExtension.fromJson 里有 4 个"抗后端漂移"
// 的兼容点(见 user_model.dart 注释),任何一项回归都会导致线上
// 解析崩或字段丢,必须用测试锁死:
// ① data 包装:接口返回 {code, message, data:{...}} 时取 data;
// ② 字符串数字:userId/classId 后端可能返回 "820466383020136";
// ③ 缺字段兜底:后端漏字段时用默认值,不闪崩;
// ④ toJson/fromJson 必须成对,否则缓存回填丢字段。
//
// 运行:flutter test test/models/user_model_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:new_learn/core/models/user_model.dart';
void main() {
group('CurrentUserExtension.fromJson', () {
test('① data 包装:取 json["data"],忽略外层 code/message', () {
final user = CurrentUserExtension.fromJson({
'code': 200,
'message': 'ok',
'data': {'userId': 1001, 'userName': '小明', 'userPoints': 88.5},
});
expect(user.userId, 1001);
expect(user.userName, '小明');
expect(user.userPoints, 88.5);
});
test('① 直接返回(没有 data 包装)也支持', () {
final user = CurrentUserExtension.fromJson({
'userId': 7,
'userName': '小李',
});
expect(user.userId, 7);
expect(user.userName, '小李');
});
test('② 字符串数字:userId/classId/userPoints 传字符串能正确转换', () {
final user = CurrentUserExtension.fromJson({
'data': {
'userId': '820466383020136', // 大数必须 int 不丢精度
'classId': '12',
'userPoints': '105.5',
'graduationYear': '2026',
},
});
expect(user.userId, 820466383020136);
expect(user.classId, 12);
expect(user.userPoints, 105.5);
expect(user.graduationYear, 2026);
});
test('② 非法字符串数字兜底为 0,不抛异常', () {
final user = CurrentUserExtension.fromJson({
'data': {'userId': 'abc', 'userPoints': 'xyz'},
});
expect(user.userId, 0);
expect(user.userPoints, 0.0);
});
test('③ 空 JSON:全部字段走默认值,不闪崩', () {
final user = CurrentUserExtension.fromJson({});
expect(user.userId, 0);
expect(user.userName, '');
expect(user.userPoints, 0.0);
expect(user.levelName, '');
expect(user.isShowGuide, false);
expect(user.isShowReport, false);
expect(user.id, 0);
});
test('④ toJson/fromJson 往返一致(缓存回填不丢字段)', () {
const user = CurrentUserExtension(
userId: 1001,
userName: '小明',
userPoints: 88.5,
levelName: '青铜',
avatar: 'https://x/a.png',
className: '高三(1)班',
classId: 12,
gradeLevel: '高三',
graduationYear: 2026,
targetConfigId: 3,
targetConfigName: '目标A',
userAvatarStatus: 1,
userAvatarReason: '待审核',
isShowGuide: true,
isShowReport: true,
id: 99,
);
final roundTrip = CurrentUserExtension.fromJson(user.toJson());
expect(roundTrip.userId, user.userId);
expect(roundTrip.userName, user.userName);
expect(roundTrip.userPoints, user.userPoints);
expect(roundTrip.levelName, user.levelName);
expect(roundTrip.className, user.className);
expect(roundTrip.isShowGuide, user.isShowGuide);
expect(roundTrip.userAvatarReason, user.userAvatarReason);
});
});
group('UserPointLevel.fromJson', () {
test('数字字段解析 + 默认值兜底', () {
final level = UserPointLevel.fromJson({
'userId': 1001,
'totalPoints': 500,
'level': 2,
});
expect(level.userId, 1001);
expect(level.totalPoints, 500);
expect(level.level, 2);
expect(level.levelUpPoints, 0); // 缺字段走默认值
final empty = UserPointLevel.fromJson({});
expect(empty.totalPoints, 0);
expect(empty.level, 0);
});
});
}