bag
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
using Xunit;
|
||||
using Yh.Platform.Abstractions;
|
||||
|
||||
namespace Yh.Platform.Abstractions.Tests;
|
||||
|
||||
public class ErrorCodeAndExceptionTests
|
||||
{
|
||||
[Fact]
|
||||
public void ErrorCode_常量值与Java一比一()
|
||||
{
|
||||
Assert.Equal(0, ErrorCode.Success.Code);
|
||||
Assert.Equal(1, ErrorCode.Error.Code);
|
||||
Assert.Equal(2, ErrorCode.ParamError.Code);
|
||||
Assert.Equal(3, ErrorCode.Forbidden.Code);
|
||||
Assert.Equal(4, ErrorCode.Unauthorized.Code);
|
||||
Assert.Equal(5, ErrorCode.Custom.Code);
|
||||
Assert.Equal(6, ErrorCode.InternalServerError.Code);
|
||||
Assert.Equal(405, ErrorCode.HttpMethodNotAllowed.Code);
|
||||
Assert.Equal("登录已经过期,请重新登录", ErrorCode.Unauthorized.Msg);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DException_便捷构造_默认Custom且message为纯msg()
|
||||
{
|
||||
var e = new DException("业务失败");
|
||||
Assert.Equal(5, e.Code!.Code);
|
||||
Assert.Equal("业务失败", e.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DException_携带code_msg_data_等价Java语义()
|
||||
{
|
||||
var code = new OpenApiLike(5, "组下存在子组或用户,禁止删除");
|
||||
var data = new { groupId = 9 };
|
||||
var e = new DException(code, code.Msg, data);
|
||||
|
||||
Assert.Equal(5, e.Code!.Code);
|
||||
Assert.Equal("组下存在子组或用户,禁止删除", e.Message);
|
||||
Assert.Same(data, e.EnvelopeData);
|
||||
}
|
||||
|
||||
private sealed record OpenApiLike(int Code, string Msg) : IErrorCode;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
global using System;
|
||||
global using System.Collections.Generic;
|
||||
global using System.IO;
|
||||
global using System.Threading;
|
||||
global using System.Threading.Tasks;
|
||||
global using Yh.Platform.Abstractions;
|
||||
@@ -0,0 +1,130 @@
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using JsonSerializer = System.Text.Json.JsonSerializer;
|
||||
using Xunit;
|
||||
using Yh.Platform.Abstractions;
|
||||
|
||||
namespace Yh.Platform.Abstractions.Tests;
|
||||
|
||||
public class ModelSerializationTests
|
||||
{
|
||||
private static JObject LoadFixtureBareData()
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "fixtures", "envelope-success.json");
|
||||
return JObject.Parse(File.ReadAllText(path))["bareData"]!.Value<JObject>()!;
|
||||
}
|
||||
|
||||
private static JObject LoadFixtureWrapped()
|
||||
{
|
||||
var path = Path.Combine(AppContext.BaseDirectory, "fixtures", "envelope-success.json");
|
||||
return JObject.Parse(File.ReadAllText(path))["wrappedData"]!.Value<JObject>()!;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Newtonsoft_反序列化fixture_含currentRole嵌套()
|
||||
{
|
||||
var user = LoadFixtureBareData().ToObject<BoaUser>(new Newtonsoft.Json.JsonSerializer
|
||||
{
|
||||
// net5 消费方形态:ASP.NET Core AddNewtonsoftJson 默认大小写不敏感、保留属性名
|
||||
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
|
||||
});
|
||||
|
||||
Assert.Equal(1001, user!.Id);
|
||||
Assert.Equal("zhangsan", user.Account);
|
||||
Assert.Equal("张三", user.Name);
|
||||
Assert.Equal(2, user.School!.Id);
|
||||
Assert.Equal("云海第一中学", user.School.Name);
|
||||
Assert.Equal(3, user.CurrentRole!.RoleId);
|
||||
Assert.Equal("教师", user.CurrentRole.RoleName);
|
||||
Assert.Equal("云海第一中学", user.CurrentRole.SchName);
|
||||
Assert.Equal(21, user.CurrentRole.ChildId);
|
||||
Assert.Equal(2, user.Schools!.Count);
|
||||
Assert.Equal(new List<int> { 3, 5 }, user.RoleIds);
|
||||
Assert.Equal(3, user.Groups!.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Newtonsoft_默认设置_大小写不敏感匹配camelCase()
|
||||
{
|
||||
var user = LoadFixtureBareData().ToObject<BoaUser>();
|
||||
Assert.Equal("zhangsan", user!.Account);
|
||||
Assert.Equal("教师", user.CurrentRole!.RoleName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SystemTextJson_Web序列化_与fixture逐节点一致()
|
||||
{
|
||||
var user = LoadFixtureBareData().ToObject<BoaUser>();
|
||||
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web)
|
||||
{
|
||||
// 对齐 Java 侧 NON_NULL 语义
|
||||
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
|
||||
};
|
||||
var json = JsonSerializer.Serialize(user, options);
|
||||
|
||||
// 语义等价:键序无关、null 节点差异容忍(fixture 中显式 null 与省略 null 视为一致)
|
||||
Assert.True(JToken.DeepEquals(JObject.Parse(json), StripNulls(LoadFixtureBareData())),
|
||||
"STJ 序列化结果应与 fixture 语义一致\n" + json);
|
||||
}
|
||||
|
||||
private static JObject StripNulls(JObject obj)
|
||||
{
|
||||
var clone = (JObject)obj.DeepClone();
|
||||
var toRemove = new List<JProperty>();
|
||||
CollectNullProps(clone, toRemove);
|
||||
foreach (var p in toRemove)
|
||||
{
|
||||
p.Remove();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
private static void CollectNullProps(JToken token, List<JProperty> collected)
|
||||
{
|
||||
foreach (var child in token.Children())
|
||||
{
|
||||
if (child is JProperty p)
|
||||
{
|
||||
if (p.Value.Type == JTokenType.Null)
|
||||
{
|
||||
collected.Add(p);
|
||||
continue;
|
||||
}
|
||||
CollectNullProps(p.Value, collected);
|
||||
}
|
||||
else if (child.Type is JTokenType.Object or JTokenType.Array)
|
||||
{
|
||||
CollectNullProps(child, collected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SystemTextJson_反序列化信封包裹成功样例()
|
||||
{
|
||||
var wrapped = LoadFixtureWrapped();
|
||||
var envelope = wrapped.ToObject<ApiEnvelope<BoaUser>>(new Newtonsoft.Json.JsonSerializer
|
||||
{
|
||||
ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver(),
|
||||
});
|
||||
|
||||
Assert.True(envelope!.IsSuccess);
|
||||
Assert.Equal(0, envelope.Code);
|
||||
Assert.Equal(1001, envelope.Data!.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BoaApp_Models_双序列化往返()
|
||||
{
|
||||
var app = new BoaApp { Id = 7, Name = "作业提交", Clients = (int)ClientEnum.PcBrowser | (int)ClientEnum.MobileApp, IsPublic = false, BuiltInTag = 0 };
|
||||
var stj = JsonSerializer.Deserialize<BoaApp>(JsonSerializer.Serialize(app, new JsonSerializerOptions(JsonSerializerDefaults.Web)), new JsonSerializerOptions(JsonSerializerDefaults.Web));
|
||||
var nf = JObject.Parse(JsonConvert.SerializeObject(app, new JsonSerializerSettings { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() })).ToObject<BoaApp>();
|
||||
|
||||
Assert.Equal(app.Name, stj!.Name);
|
||||
Assert.Equal(app.Clients, stj.Clients);
|
||||
Assert.Equal(app.Name, nf!.Name);
|
||||
Assert.Equal(false, nf.IsPublic);
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Yh.Platform.Abstractions\Yh.Platform.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\..\contract\fixtures\**\*.*" CopyToOutputDirectory="PreserveNewest" LinkBase="fixtures" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user