You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 5项目xUnit测试Visual Studio运行正常但dotnet test命令行执行时出现序列化相关灾难性错误

问题原因分析与解决办法

我之前也碰到过类似的xUnit命令行测试崩溃的问题,咱们来一步步拆解这个问题:

问题根源

你遇到的崩溃只在dotnet test命令行执行时出现,且仅针对使用自定义record类型TruncatedString作为Theory测试参数的场景,核心原因是xUnit命令行测试运行器的序列化机制无法处理你的自定义record类型:

  • Visual Studio的测试宿主和dotnet test用的参数传递逻辑不同:VS测试宿主可以通过进程内直接传递对象的方式避免序列化,但dotnet test依赖xUnit的跨进程消息传递系统,必须把测试参数序列化后才能传递给测试执行进程。
  • 你的TruncatedString中Value是protected属性,xUnit使用的序列化器无法访问这个成员;同时该record没有提供自定义序列化逻辑,导致序列化整个参数数组时失败,触发了ArgumentException错误。

具体解决办法

方案1:调整TruncatedString的成员访问级别(最简便)

把Value属性改成public,让序列化器能正常读取它的内容,record的默认序列化就能正常工作:

public record TruncatedString
{
    public TruncatedString(string value)
    {
        Value = FormatTruncatedString(value);
    }
    // 将protected改为public
    public string Value { get; }
    protected static string FormatTruncatedString(string value)
    {
        return value?.Substring(0,4) ?? string.Empty;
    }
    public static implicit operator string(TruncatedString truncated) => truncated.Value;
    public static implicit operator TruncatedString(string text) => new (text);
    public override string ToString() => Value;
}

方案2:在测试内部转换参数类型(不修改原类型)

如果不想改动TruncatedString的访问权限,可以把InlineData的参数换成string,在测试方法内部再转换成TruncatedString:

[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("ABC")]
public async Task ThestWithTheErrorMessage(string value)
{
    // 内部完成类型转换
    TruncatedString truncatedValue = value;
    // ... 你的测试逻辑
}

这样xUnit只需要序列化原生的string类型,完全避开自定义类型的序列化问题,同时不影响测试逻辑。

方案3:为TruncatedString添加自定义序列化逻辑(适合必须保留protected成员的场景)

如果必须保留protected的Value,可以实现ISerializable接口手动控制序列化过程:

using System.Runtime.Serialization;

public record TruncatedString : ISerializable
{
    public TruncatedString(string value)
    {
        Value = FormatTruncatedString(value);
    }

    // 反序列化专用构造函数
    protected TruncatedString(SerializationInfo info, StreamingContext context)
    {
        Value = info.GetString(nameof(Value)) ?? string.Empty;
    }

    protected string Value { get; }
    protected static string FormatTruncatedString(string value)
    {
        return value?.Substring(0,4) ?? string.Empty;
    }
    public static implicit operator string(TruncatedString truncated) => truncated.Value;
    public static implicit operator TruncatedString(string text) => new (text);
    public override string ToString() => Value;

    // 自定义序列化逻辑
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue(nameof(Value), Value);
    }
}

这个方案让你能完全控制序列化过程,即使Value是protected也能被正常序列化和反序列化。

验证

修改完成后,重新运行dotnet test,应该就不会再出现进程崩溃的问题了。

内容的提问来源于stack exchange,提问作者Diego

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:09:08