如何在伪造 属性 时指定要使用的 class?

How to specify the class to use when faking a property?

我发现我经常伪造来自 Entity Framework 的 IDbSet。我通常有这样的界面:

public interface IContext : IDisposable
{
    IDbSet<Cat> Cats { get; set; }
    IDbSet<Dogs> Dogs { get; set; }
}

我是这样伪造的:

IContext context = A.Fake<IContext>();
context.Cats = new FakeDbSet<Cat>();
context.Dogs = new FakeDbSet<Dogs>();

最后两行代码变得很痛苦。
FakeDbSet 是一个自定义的 class,我们总是想用它来代替 FakeItEasy 假的。

有什么方法可以让 FakeItEasy 在任何它看到 IDbSet 的地方使用 FakeDbSet?

Is there some way I can just tell FakeItEasy that anywhere it sees an IDbSet, use FakeDbSet?

不是这样,不是。有 custom Dummies, whose powers are vastly improved in the upcoming 2.0 release, but currently properties do not return Dummies when they can return a fakeable type (see issue 156 的信息可能太多了)。否则,你就完事了。

否则,最好的选择确实是使用反射来查看属性的 return 类型并相应地设置值。

您可以使用 newly-expanded IFakeConfigurator powers in the 2.0 betas 作为启用此行为的挂钩,因此创建的每个假货都会检查其属性并添加所需的 FakeDbSet

像这样:

public class PropertiesUseFakeDbSetFakeConfigurator : FakeConfigurator<IContext>
{
    protected override void ConfigureFake(IContext fakeObject)
    {
        var fakeObjectType = fakeObject.GetType();
        var properties = fakeObjectType.GetProperties(
            BindingFlags.Public |
            BindingFlags.Instance |
            BindingFlags.GetProperty |
            BindingFlags.SetProperty);

        foreach (var propertyInfo in properties)
        {
            var propertyType = propertyInfo.PropertyType;
            if (propertyType.IsGenericType &&
                propertyType.GetGenericTypeDefinition() == typeof (IDbSet<>))
            {
                var typeInTheSet = propertyType.GetGenericArguments()[0];
                var fakeDbSetType = typeof (FakeDbSet<>).MakeGenericType(typeInTheSet);
                var fakePropertyValue = Activator.CreateInstance(fakeDbSetType);

                propertyInfo.SetValue(fakeObject, fakePropertyValue, null);
            }
        }
    }
}

会通过:

[Test]
public void Properties_should_be_FakeDbSets()
{
    IContext context = A.Fake<IContext>();

    Assert.That(context.Cats, Is.InstanceOf<FakeDbSet<Cat>>());
    Assert.That(context.Dogs, Is.InstanceOf<FakeDbSet<Dog>>());
}

如果您的解决方案中有多个 类,例如 IContext,您可能希望直接实施 IFakeConfigurator,而不是使用 FakeConfigurator<T>。它需要做更多的工作,但提供了一种更复杂的方法来确定配置了 哪些 假货。 FakeConfigurator<IContext> 只会配置伪造的 IContexts.