c# – 使用AutoFixture,XUnit和Moq始终冻结模拟

前端之家收集整理的这篇文章主要介绍了c# – 使用AutoFixture,XUnit和Moq始终冻结模拟前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用AutoFixture,Moq和XUnit扩展([Theory]属性),如本博文 http://blog.ploeh.dk/2010/10/08/AutoDataTheorieswithAutoFixture中所述.

我注意到大多数单元测试看起来像这样:

[Theory,AutoMoqData]
public void Test(
    [Frozen] Mock<IServiceOne> serviceOne,[Frozen] Mock<IServiceTwo> serviceTwo,MyClass classUnderTest)
{
    // Arrange
    serviceOne
        .Setup(m => m.Get(It.IsAny<int>()));

    serviceTwo
        .Setup(m => m.Delete(It.IsAny<int>()));

    // MyClass has a constructor with arguments for IServiceOne,and IServiceTwo
    // classUnderTest will use the two mocks specified above

    // Act
    var result = classUnderTest.Foo();

    // Assert
    Assert.True(result);
}

与总是使用[Frozen]装饰模具相反,是否有办法设置夹具以始终冻结模具?

这是AutoMoqData属性

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(new Fixture().Customize(new AutoMoqCustomization()))
    {
    }
}

解决方法

虽然它目前不是内置的,但是编写一个通用的Decorator很容易,当它们离开AutoFixture Tree of Responsibility时冻结对象:
public class MemoizingBuilder : ISpecimenBuilder
{
    private readonly ISpecimenBuilder builder;
    private readonly ConcurrentDictionary<object,object> instances;

    public MemoizingBuilder(ISpecimenBuilder builder)
    {
        this.builder = builder;
        this.instances = new ConcurrentDictionary<object,object>();
    }

    public object Create(object request,ISpecimenContext context)
    {
        return this.instances.GetOrAdd(
            request,r => this.builder.Create(r,context));
    }
}

请注意,它装饰另一个ISpecimenBuilder,但在返回之前记住所有值.如果同一请求再次到达,它将返回memoized值.

虽然您无法扩展AutoMoqCustomization,但您可以复制它的功能(它只有两行代码),并使用它周围的MemoizingBuilder:

public class AutoFreezeMoq : ICustomization
{
    public void Customize(IFixture fixture)
    {
        if (fixture == null)
            throw new ArgumentNullException("fixture");

        fixture.Customizations.Add(
            new MemoizingBuilder(
                new MockPostprocessor(
                    new MethodInvoker(
                        new MockConstructorQuery()))));
        fixture.ResidueCollectors.Add(new MockRelay());
    }
}

使用此AutoFreezeMoq而不是AutoMoqCustomization.它将冻结所有模拟,以及从这些模拟创建的所有接口和抽象基类.

public class AutoMoqDataAttribute : AutoDataAttribute
{
    public AutoMoqDataAttribute()
        : base(new Fixture().Customize(new AutoFreezeMoq()))
    {
    }
}

猜你在找的C#相关文章