c# - 使用 AutoFixture 实例化 [immutable] 对象时指定 [readonly] 属性值 [via ctor args]

标签 c# unit-testing immutability autofixture

我的测试要求我设置 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# 中的一个难题,但您可以更轻松地使用 Rsvp 这样的类如果您从 F# 中得到启发并引入复制和更新 语义。如果修改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方法作为扩展方法。

一旦你这样做了十几次,你就会厌倦它,是时候转移到 F# 了,所有这些(以及更多)都是内置的:

type Rsvp = {
    Response : string
    CreatedDate : DateTime }

您可以创建一个 Rsvp像这样用 AutoFixture 记录:

let fixture = Fixture()
let seed = fixture.Create<Rsvp>()
let sut = { seed with Response = "Attending" }

或者,作为单行:

let sut = { Fixture().Create<Rsvp>() with Response = "Attending" }

关于c# - 使用 AutoFixture 实例化 [immutable] 对象时指定 [readonly] 属性值 [via ctor args],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20808755/

相关文章:

c# - 在 Web Api 2 中启用 CORS

c# - WCF channel 工厂缓存

c# - EF 迁移应该去哪里,我的类库项目还是我的 ASP.NET 项目?

php - 如何重置对 PHPUnit 模拟对象的期望

python - 如何在 Tkinter 应用程序上运行 unittest?

java - 不可变类的例子

c# - 如何为一个列表中的不同类型的值设计工厂模式?

python - nosetest - 获取失败测试列表(无额外输出)

c# - ReadOnlyCollection vs Liskov - 如何正确建模可变集合的不可变表示

swift - 在服务器上创建模型的正确方法