129 lines
4.1 KiB
Dart
129 lines
4.1 KiB
Dart
// 单元测试: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);
|
||
});
|
||
});
|
||
}
|