AutoFixture 和动态夹具类型注入

AutoFixture and dynamic fixture type Injections

我是 AutoFixture 的新手,在尝试动态冻结和注入类型时遇到了一些问题。这是我在各处重复使用的代码示例,以将伪造的存储库注入到我的设备中:

FakeRepository<Application> applicationRepository = fixture.Freeze<FakeRepository<Application>>();
fixture.Inject<IReadRepository<Application>>(applicationRepository);
fixture.Inject<IWriteRepository<Application>>(applicationRepository);

在使用反射动态获取实体程序集中的所有类型后,我想做这样的事情:

Type repositoryReadInterfaceType = typeof(IReadRepository<>).MakeGenericType(entityType);
Type repositoryWriteInterfaceType = typeof(IWriteRepository<>).MakeGenericType(entityType);
Type repositoryType = typeof(FakeRepository<>).MakeGenericType(entityType);

var repositoryObject = fixture.Freeze(repositoryType);
fixture.Inject(repositoryReadInterfaceType, repositoryObject);
fixture.Inject(repositoryWriteInterfaceType, repositoryObject);

但是,没有支持我想要的所需注入的重载。我还缺少其他解决方法吗?或者,也许,这是不可能的?

根据我的尝试进行编辑:

尝试 1 使用 TypeRelay:

var repositoryObject = fixture.Freeze(repositoryType);

fixture.Customizations.Add(new TypeRelay(repositoryReadInterfaceType, repositoryType));
fixture.Customizations.Add(new TypeRelay(repositoryWriteInterfaceType, repositoryType));

尝试 2 使用 SpecimenBuilderNodeFactory:

var repositoryObject = fixture.Freeze(repositoryType);

fixture.Customizations.Insert(
    0,
    SpecimenBuilderNodeFactory.CreateTypedNode(
        repositoryReadInterfaceType,
        new FixedBuilder(repositoryObject)
    )
);
fixture.Customizations.Insert(
    0,
    SpecimenBuilderNodeFactory.CreateTypedNode(
        repositoryWriteInterfaceType,
        new FixedBuilder(repositoryObject)
    )
);

仅使用动态冻结的尝试3:

在一个单独的使用反射的方法中,我冻结了所有的假存储库,如下所示:

var repositoryObject = fixture.Freeze(repositoryType);

然后在我的主要方法中,我手动注入读写存储库类型:

fixture.Inject<IReadRepository<Application>>(fixture.Create<FakeRepository<Application>>());
fixture.Inject<IWriteRepository<Application>>(fixture.Create<FakeRepository<Application>>());

以上所有尝试都会导致读取和写入类型似乎不指向同一个 FakeRepository。

更新后的答案,原来的在下面

此重现有效(测试通过):

public interface IFoo
{
    string FooIt();
}

public interface IBar
{
    string BarIt();
}

public class FooBar : IFoo, IBar
{
    public FooBar(Guid id)
    {
        this.Id = id;
    }

    public Guid Id { get; private set; }

    public string BarIt()
    {
        return this.Id.ToString();
    }

    public string FooIt()
    {
        return this.Id.ToString();
    }
}

public class Tests
{
    [Fact]
    public void AllIsFrozen()
    {
        var fixture = new Fixture();
        fixture.Customize(new FreezingCustomization(typeof(FooBar)));
        fixture.Customizations.Add(new TypeRelay(typeof(IFoo), typeof(FooBar)));
        fixture.Customizations.Add(new TypeRelay(typeof(IBar), typeof(FooBar)));

        var foo = fixture.Create<IFoo>();
        var bar = fixture.Create<IBar>();
        var foobar = fixture.Create<FooBar>();

        Assert.Equal(foobar.Id.ToString(), foo.FooIt());
        Assert.Equal(foobar.Id.ToString(), bar.BarIt());
    }
}

原回答

我没试过,所以它可能既不能编译也不能工作...

你注入的所有东西最终都会打包成一个 ISpecimenBuilder 并放在 Fixture.Customizations 中。您可以尝试使用 FixedBuilder 并将其打包到类型节点中。

类似这样的方法可行:

fixture.Customizations.Insert(
    0,
    SpecimenBuilderNodeFactory.CreateTypedNode(
        myType,
        new FixedBuilder(myObject)));

您也可以使用 Customizations.Add,但请注意该集合中的顺序很重要(第一场比赛获胜)。