我的测试要求将不可变Response
对象(请参见下文)上的Rsvp
属性设置为特定值。
public class Rsvp
{
public string Response { get; private set; }
public Rsvp(string response)
{
Response = response;
}
}
我最初尝试使用
Build<Rsvp>().With(x => x.Rsvp, "Attending")
做到这一点,但意识到这仅支持可写属性。我用
Build<Rsvp>().FromFactory(new Rsvp("Attending"))
代替了它。这是可行的,但是对于更复杂的对象来说是麻烦的,这些对象的某些属性无关紧要。例如,如果
Rsvp
对象具有CreatedDate
属性,则这种实例化该对象的方法将迫使我编写Build<Rsvp>().FromFactory(new Rsvp("Attending", fixture.Create<DateTime>()))
。有没有一种方法只能为不可变对象(immutable对象)的含义属性指定值?
最佳答案
AutoFixture最初是作为测试驱动开发(TDD)的工具构建的,而TDD的全部内容都是反馈。本着GOOS的精神,您应该收听测试。如果测试难以编写,则应考虑API设计。 AutoFixture倾向于放大这种反馈。
坦白地说,不可变类型是C#中的一个难题,但是如果您从F#中获取线索并引入复制并更新语义,则可以简化使用Rsvp
之类的类的工作。如果您这样修改Rsvp
,则从整体上来说将更加容易,因此,作为副产品,也将进行单元测试:
public class Rsvp
{
public string Response { get; private set; }
public DateTime CreatedDate { get; private set; }
public Rsvp(string response, DateTime createdDate)
{
Response = response;
CreatedDate = createdDate;
}
public Rsvp WithResponse(string newResponse)
{
return new Rsvp(newResponse, this.CreatedDate);
}
public Rsvp WithCreatedDate(DateTime newCreatedDate)
{
return new Rsvp(this.Response, newCreatedDate);
}
}
请注意,我添加了两个
WithXyz
方法,这些方法返回一个新实例,其中一个值已更改,但所有其他值保持不变。这将使您能够创建
Rsvp
实例来进行测试,如下所示:var fixture = new Fixture();
var seed = fixture.Create<Rsvp>();
var sut = seed.WithResponse("Attending");
或者,单线:
var sut = new Fixture().Create<Rsvp>().WithResponse("Attending");
如果您不能更改
Rsvp
,则可以将WithXyz
方法添加为扩展方法。完成大约12次之后,您会厌倦了,现在该迁移到F#了,所有这些(以及更多)都是内置的:
type Rsvp = {
Response : string
CreatedDate : DateTime }
您可以使用AutoFixture创建
Rsvp
记录,如下所示:let fixture = Fixture()
let seed = fixture.Create<Rsvp>()
let sut = { seed with Response = "Attending" }
或者,单线:
let sut = { Fixture().Create<Rsvp>() with Response = "Attending" }
关于c# - 使用AutoFixture实例化[不可变]对象时,指定[只读]属性值[通过ctor args],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20808755/