如何将基于约定的自定义与 AutoFixture 的 [AutoData] 属性相结合?

How to combine a Convention-based Customization with AutoFixture's [AutoData] attribute?

我正在使用 AutoFixture's [AutoData] 属性来提供一些带有 POCO 实例的单元测试 (NUnit)。例如:

[Test, AutoData]
public void Create_NameIsNull_ThrowsException(MyPOCO myPOCO) {..}

我最近向我的 POCO 添加了一个新字符串 属性,它必须始终包含格式正确的 URL。

自然地,[AutoData] 不知道这个要求,并为此 属性 生成通常的基于 GUID 的字符串值。这导致我的测试失败(因为我已经进行了一些基于 Data Annotations 的验证)。

我听从了@ploeh 的建议并为 AutoFixture 编写了一个 Convention-based Customization,它专门为我的这个新 属性 生成一个格式正确的 URL 字符串。它是一个名为 UrlSpecimenBuilder 的 class 实现了 ISpecimenProvider.

我的问题是,如何将我的新 ISpecimenProvider[AutoData] 结合起来?

我不想在我的每一个单元测试中都进行 fixture.Customizations.Add(new UrlSpecimenBuilder());。我正在寻找一个可以做同样事情的测试夹具设置步骤。

您应该定义自己的 AutoDataAttribute 版本并应用您需要的所有自定义设置。如果定制与所有测试相关,它可能被称为 DefaultAutoData:

[Test, DefaultAutoData]
public void Create_NameIsNull_ThrowsException(MyPOCO myPOCO) {..}

internal class DefaultAutoDataAttribute : AutoDataAttribute
{
  public DefaultAutoDataAttribute()
    : base(new Fixture().Customizations.Add(new UrlSpecimenBuilder()))
  {
  }
}

详情见this Mark Seemann post

您还可以重写 CustomizeAttribute 以获得类似

的语法
[Test, AutoData]
public void Create_NameIsNull_ThrowsException(
  [MyPOCOWithValidUrl] MyPOCO myPOCO) 
{..}

Some real world examples