我的测试要求将不可变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/

10-10 02:13