6

我真的很欣赏 AutoFixture 的强大功能以及 XUnit 的理论。我最近采用了封装自定义并通过属性将它们提供给我的测试的方法。

在某些情况下,我需要一个一次性的场景来运行我的测试。当我像上面一样使用 AutoDomainDataAttribute 时,我可以要求一个 IFixture 并期望获得由该属性创建的相同实例吗?

在我的场景中,默认情况下我对集合等使用 MultipleCustomization。但是,在这种情况下,我只希望将单个项目发送到我的 SUT 的构造函数。所以,我已经像这样定义了我的测试方法:

[Theory, AutoDomainData]
public void SomeTest(IFixture fixture) {
  fixture.RepeatCount = 1;
  var sut = fixture.CreateAnonymous<Product>();
  ...
}

不幸的是,我在创建匿名产品时遇到了异常。如果我要求 Product 作为具有这些属性的方法参数,其他测试工作得很好。在这种特殊情况下,这只是一个问题,我希望fixture 参数与我的AutoDomainDataAttribute 创建的参数相同。

由于我通过 AutoDomainData 进行了就地自定义,产品的构造函数需要一个 IEnumerable,该 IEnumerable 通常会填充 3 个项目。目前,我的 DomainCustomization 是由 MultipleCustomization 和 AutMoqCustomization 按顺序组成的 CompositeCustomization。

例外是:“InvalidCastException:无法将 'Castle.Proxies.ObjectProxy' 类型的对象转换为 'Product' 类型。”

4

1 回答 1

7

如果您需要与属性中的活动实例相同的 Fixture 实例,则可以在自定义中将 Fixture 注入自身,如下所示:

public class InjectFixtureIntoItself : ICustomization
{
    public void Customize(IFixture fixture)
    {
        fixture.Inject(fixture);
    }
}

请记住在 AutoMoqCustomization之前将其添加到您的 CompositeCustomization中,因为 IFixture 是一个接口,如果 AutoMoqCustomization 先出现,您将获得一个 Mock 实例 - AFAICT,这就是动态 Castle 代理目前正在发生的事情。


然而,如果你真的需要一个 Fixture 实例,为什么不写一个常规的、命令式的测试方法:

[Fact]
public void SomeTest()
{
    var fixture = new Fixture().Customize(new DomainCustomization());
    fixture.RepeatCount = 1;
    var sut = fixture.CreateAnonymous<Product>();
    // ...
}

在我看来这要容易得多......我自己也偶尔这样做......


不过,我想知道您是否不能以不同的方式来表达您的 API 或测试用例以使整个问题消失。这些天我很少发现我必须操纵RepeatCount财产,所以我想知道你为什么要这样做?

不过,这可能是另一个 Stack Overflow 问题的主题......

于 2012-10-29T20:27:12.893 回答