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

如何正确测试ICollection类型属性是否返回真正的只读集合?

如何正确测试集合 getter 返回真正的只读集合

你说得对,选项1的断言完全不靠谱——毕竟List<string>确实实现了IReadOnlyCollection<string>,但它本质还是可变的,客户端拿到之后转成List<string>就能随便修改。要测试返回的是真正不可被客户端修改的集合,得从「行为」入手,而不是只看类型。

下面是两种靠谱的测试方式:

方法1:尝试修改集合,验证会抛出异常

这是最直接且有效的方式,因为真正的只读集合(比如ReadOnlyCollection<string>、ImmutableArray<string>或者用List.AsReadOnly()包装的实例)在尝试执行添加/移除/清除操作时,会抛出NotSupportedException。

示例测试代码(以NUnit为例):

[Test]
public void MyCollection_ReturnsTrulyReadOnlyCollection()
{
    // Arrange
    var model = new Model();

    // Act & Assert
    Assert.Throws<NotSupportedException>(() => model.MyCollection.Add("test"));
    Assert.Throws<NotSupportedException>(() => model.MyCollection.Remove("any"));
    Assert.Throws<NotSupportedException>(() => model.MyCollection.Clear());
}

因为你的MyCollection声明为ICollection<string>,这三个操作是接口定义的标准方法,直接调用即可。不管内部用的是什么只读实现,只要客户端没法修改,测试就会通过。

方法2:验证返回的集合是不可变的具体类型(可选辅助验证)

如果你明确知道内部应该返回某个特定的只读类型(比如ReadOnlyCollection<string>或者ImmutableList<string>),也可以加上类型断言,但这不能替代行为测试——因为未来如果换成另一种合规的只读实现,类型断言会失败,但行为依然符合要求。不过可以作为辅助验证:

Assert.That(model.MyCollection, Is.TypeOf<ReadOnlyCollection<string>>());

额外提醒:确保类内部的实现正确

要让测试通过,你的Model类内部必须确保返回的是包装后的只读实例,而不是直接返回可变集合的引用。比如正确的实现应该是这样:

public class Model 
{
    private readonly List<string> _internalList = new();
    public ICollection<string> MyCollection => _internalList.AsReadOnly();
}

这样返回的ReadOnlyCollection<string>不仅在尝试修改时会抛异常,也无法被强制转成List<string>来绕过只读限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 08:20:08