c# - Always Freeze 使用 AutoFixture、XUnit 和 Moq 进行模拟

标签 c# unit-testing moq xunit.net autofixture

我正在使用这篇博文 http://blog.ploeh.dk/2010/10/08/AutoDataTheorieswithAutoFixture 中描述的 AutoFixture、Moq 和 XUnit 扩展([Theory] 属性) .

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

[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] 装饰模拟相反,有没有办法设置 fixture 总是卡住模拟?

这是 AutoMoqData 属性:

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

最佳答案

虽然它目前不是内置的,但很容易编写一个通用的装饰器,在对象离开 AutoFixture 责任树时将其卡住:

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,但在返回之前会记住所有值。如果相同的请求再次到达,它将返回内存值。

虽然您不能扩展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。它将卡住所有模拟,以及从这些模拟创建的所有接口(interface)和抽象基类。

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

关于c# - Always Freeze 使用 AutoFixture、XUnit 和 Moq 进行模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20955757/

相关文章:

c# - Interlocked.Exchange 可以交换两个 byte[] 数组吗?

javascript - 如何检查注入(inject) Controller 中的功能?

java - Selenium:动态按钮和类?

angular - 从服务返回的 Observable 的单元测试值(使用异步管道)

c# - 起订量 : how can mock property and side Effect?

unit-testing - 如何在使用 VirtualPathUtility.GetAbsolute 方法对代码进行单元测试时模拟上下文

silverlight-4.0 - Silverlight 4 中的最小起订量内部接口(interface)。 "Can not create proxy for types that are not accessible."

c# - DataTable.Load 跳到多结果 DataReader 中的下一个结果集

c# - NullReferenceException 添加到字典中 - 非常确定没有什么是空的

c# - mysql 不接受正确格式的小数