如何在 AutoDataAttribute sub类 中创建 Mock 类?

How to create Mock classes in AutoDataAttribute subclasses?

我目前有一个名为 ExampleViewModelAttribute 的 class,它派生自 TestViewModelDataAttribute,后者 class 派生自 AutoDataAttribute class。

public class TestViewModelDataAttribute : AutoDataAttribute
{
    public TestViewModelDataAttribute()
        : this(new Fixture())
    {

    }

    public TestViewModelDataAttribute(IFixture fixture)
        : base(fixture)
    {
        Fixture.Customize(new ViewModelsCustomization());
        Fixture.Inject(Fixture);
    }
}


public class ExampleViewModelAutoDataAttribute : TestViewModelAutoDataAttribute
{
    public ExampleViewModelAutoDataAttribute()
    {
        var someExampleMock = Fixture.Create<Mock<ISomeExampleMock>>();
        Fixture.Inject(someExampleMock);
    }
}

我的问题是,我不断收到警告“夹具是为了提高性能效率而延迟创建的,因此这个 属性 已被弃用,因为它会立即激活夹具。” + “如果您需要自定义夹具,请在传递给构造函数的工厂方法中执行此操作。”

如何修复此警告?我想在夹具中注入模拟 classes,我只得到一个答案可以帮助我修复基础 class 警告,但我还需要修复注入模拟 classes。

修复基础 class

public class TestViewModelDataAttribute : AutoDataAttribute
{
    public TestViewModelDataAttribute() : base(() =>
    {
        var fixture = new Fixture().Customize(new CompositeCustomization(
            new AutoMoqCustomization(),
            new SupportMutableValueTypesCustomization()));

        return fixture;
    })
    {
    }
}

这是我从以下答案中得到的 When setting up a custom AutoDataAttribute for auto mocking, what's the proper syntax to tell AutoFixture to ignore all recursive structures?

但是由于我在派生的 class 中使用了 属性 的 Fixture,我仍然会出错。我应该如何解决这个问题? 谢谢

您不应使用 AutoDataAttribute 中的 Fixture 属性,它可能会在版本 5 中被删除。

如果您尝试在将模拟注入测试之前设置模拟,您可以尝试创建一个定制来执行此操作。

public class MockValuesSetupCustomization : ICustomization
{
    public void Customize(IFixture fixture)
    {
        var myMock = fixture.Freeze<Mock<ISomeExampleMock>>();
        myMock.Setup(x => x.DoSomething()).Returns("something");
    }
}

当您自定义自动数据属性时,您可以使用此自定义来自定义夹具。

public class TestViewModelDataAttribute : AutoDataAttribute
{
    public TestViewModelDataAttribute()
       : base(() => new Fixture()
            .Customize(
                new CompositeCustomization(
                    new AutoMoqCustomization(),
                    new SupportMutableValueTypesCustomization(),
                    new MockValuesSetupCustomization())))
    {
    }
}

如果你只是需要一些依赖来解析 Mock<ISomeExampleMock> 那么你不需要做任何事情,因为 AutoMoqCustomization 会自动为任何接口创建模拟。 然后,您可以通过在测试方法参数中冻结它们来访问这些注入的模拟。

假设您使用的是 xUnit,您的测试将如下所示。

[Theory]
[TestViewModelData]
public void ShouldReturnExpectedResult(
    [Frozen] Mock<ISomeExampleMock> someExampleMock,
    ClassUnderTest sut)
{
    sut.DoStuff();

    someExampleMock.Verify(x => x.DoSomething(), Times.Once);
}