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

xUnit测试对比List失败问题排查及单元测试合法性咨询

修复xUnit测试失败问题 & 单元测试合法性解答

一、修复单元测试失败

你的测试失败原因是引用类型的 equality 比较逻辑问题:
当你使用 got.Should().Equal(want) 时,FluentAssertions 默认会比较对象的引用是否相同,但反序列化生成的 ContactsFilter 实例、以及内部的 groups 列表,都是全新的对象,和你手动创建的 want 集合里的实例引用完全不同,因此断言失败。

你有两种简单的修复方案:

方案1:使用结构相等断言(推荐)

改用 FluentAssertions 的 BeEquivalentTo 方法,它会递归比较对象的属性值,而不是引用:

[Fact] 
public void Should_Return_List() { 
    // arrange 
    var want = new List<ContactsFilter>() { 
        new ContactsFilter() { cms = "asees", groups = new List<string>{ "jio", "jiso" } }, 
        new ContactsFilter() { cms = "bsees", groups = new List<string>{ "jto"} } 
    }; 
    var got = new CmsContacts().GetFilters(Filters); 
    // 替换成结构相等断言
    got.Should().BeEquivalentTo(want); 
}

方案2:重写实体类的相等比较逻辑

给 ContactsFilter 重写 Equals 和 GetHashCode 方法,让默认的 equality 比较基于属性值而非引用:

public class ContactsFilter { 
    public string cms { get; set; } 
    public List<string> groups { get; set; } 

    public override bool Equals(object obj) {
        if (obj is not ContactsFilter other) return false;
        // 比较cms,再比较groups的序列是否一致
        return string.Equals(cms, other.cms) && 
               (groups?.SequenceEqual(other.groups) ?? other.groups == null);
    }

    public override int GetHashCode() {
        // 基于属性值生成哈希码
        return HashCode.Combine(cms, groups != null ? string.Join("|", groups) : null);
    }
}

这种方法需要修改实体类,适合需要频繁做值比较的场景。


二、针对JsonSerializer.Deserialize的单元测试是否合法?

这个问题要结合你的测试目标来看:

  • 如果你的GetFilters只是单纯包装框架方法:比如当前代码里只是直接调用JsonSerializer.Deserialize,没有任何自定义逻辑(比如指定反序列化选项、数据转换、验证、异常处理等),那这个测试本质是在验证System.Text.Json库的正确性,属于框架的测试范畴,测试价值很低,甚至没必要写——因为微软已经为他们的框架做了充分测试。
  • 如果你的GetFilters包含自定义逻辑:比如你给反序列化指定了特殊的JsonSerializerOptions、对结果做了过滤/转换、处理了反序列化异常等,那这个测试就是合法且有意义的——你测试的是你的代码如何使用框架,确保自定义逻辑符合预期。

举个有意义的测试场景例子:

public IEnumerable<ContactsFilter> GetFilters(string json) { 
    var options = new JsonSerializerOptions {
        PropertyNameCaseInsensitive = true // 自定义选项:忽略属性大小写
    };
    var filters = JsonSerializer.Deserialize<List<ContactsFilter>>(json, options);
    // 自定义逻辑:过滤掉cms为空的项
    return filters?.Where(f => !string.IsNullOrEmpty(f.cms)) ?? Enumerable.Empty<ContactsFilter>();
}

这时候写单元测试就能验证“忽略大小写反序列化”和“过滤空cms”的逻辑是否正常工作。

内容的提问来源于stack exchange,提问作者Tech with Thiru

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 00:57:42