AutoFixture和动态夹具类型注射

时间:2016-12-09 23:40:07

标签: c# autofixture

我对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);

然而,没有超载可以支持我想要的注射。还有其他方法可以解决这个问题吗?或者,也许,这是不可能的?

根据我的尝试进行编辑:

使用TypeRelay尝试1:

var repositoryObject = fixture.Freeze(repositoryType);

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

使用SpecimenBuilderNodeFactory尝试2:

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:

在使用Reflection的单独方法中,我冻结所有虚假存储库,如下所示:

var repositoryObject = fixture.Freeze(repositoryType);

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

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

上述所有尝试都会导致读取和写入类型看起来没有指向同一个FakeRepository。

1 个答案:

答案 0 :(得分:1)

更新了答案,原文进一步向下

此重复工作(测试通过):

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,但请注意该集合中的顺序很重要(第一场比赛获胜)。