如何使用AutoFixture为被测类的只读属性指定自定义值?
用AutoFixture设置公共只读属性的方法
根据只读属性的实现方式,有几种不同的解决办法:
1. 只读属性通过构造函数初始化
如果你的类是通过构造函数参数来初始化只读属性的(这是最推荐的设计方式),AutoFixture可以直接通过With方法指定对应属性的值,它会自动匹配到构造函数参数:
// 被测类示例 public class SomeClass { public int SomeReadonlyProperty { get; } public SomeClass(int someReadonlyProperty) { SomeReadonlyProperty = someReadonlyProperty; } } // 测试代码 var targetValue = 42; var sut = _fixture.Build<SomeClass>() .With(m => m.SomeReadonlyProperty, targetValue) .Create();
也可以直接指定构造函数参数名来赋值:
var sut = _fixture.Build<SomeClass>() .With("someReadonlyProperty", targetValue) .Create();
2. 只读属性无对应构造函数参数(私有setter或内部初始化)
如果只读属性没有公开的构造函数参数可以利用,只能通过反射修改属性值。可以在Build链中用Do方法完成:
var targetValue = "自定义值"; var sut = _fixture.Build<SomeClass>() .Do(instance => { var property = typeof(SomeClass).GetProperty(nameof(SomeClass.SomeReadonlyProperty)); // 获取私有setter方法 var setterMethod = property.GetSetMethod(true); setterMethod.Invoke(instance, new object[] { targetValue }); }) .Create();
如果需要重复使用这个逻辑,可以封装成自定义定制器:
public class SomeClassCustomization : ICustomization { private readonly string _customValue; public SomeClassCustomization(string customValue) => _customValue = customValue; public void Customize(IFixture fixture) { fixture.Customize<SomeClass>(composer => composer .Do(instance => { var prop = typeof(SomeClass).GetProperty(nameof(SomeClass.SomeReadonlyProperty)); var setter = prop.GetSetMethod(true); setter.Invoke(instance, new object[] { _customValue }); })); } } // 使用定制器 _fixture.Customize(new SomeClassCustomization("重复使用的自定义值")); var sut = _fixture.Create<SomeClass>();
3. C# 9+的Init-Only属性
如果你的只读属性是用get; init;声明的(C# 9及以上版本),AutoFixture 4.15.0及以上版本支持直接用With方法设置,无需额外操作:
// 被测类示例 public class SomeClass { public string SomeInitOnlyProperty { get; init; } } // 测试代码 var targetValue = "Init值"; var sut = _fixture.Build<SomeClass>() .With(m => m.SomeInitOnlyProperty, targetValue) .Create();
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

