【问题标题】:How to specify the class to use when faking a property?伪造属性时如何指定要使用的类?
【发布时间】:2015-03-29 08:47:50
【问题描述】:

我发现我经常从实体框架中伪造 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 是一个自定义类,我们总是希望使用它来代替 FakeItEasy 假货。

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

【问题讨论】:

  • 我知道我可以反思假货并自己分配 FakeDbSet,但我希望有一个内置的方法。

标签: fakeiteasy


【解决方案1】:

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

不是这样,不。有custom Dummies,其功能在即将发布的 2.0 版本中得到了极大的改进,但当前属性在可以返回可伪造类型时不会返回 Dummies(请参阅 issue 156 可能有太多关于这方面的信息)。否则,你就万事大吉了。

如果做不到这一点,最好的选择确实是使用反射来查看属性的返回类型并相应地设置值。

您可以使用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&lt;T&gt;。它需要更多的工作,但提供了一种更复杂的方法来确定配置了 哪些 假货。 FakeConfigurator&lt;IContext&gt; 只会配置伪造的IContexts。

【讨论】:

  • 哇,感谢您花时间写这篇文章,以及您在 FakeItEasy 上所做的所有工作。继续加油!
  • 没问题。说实话,虽然我会更乐意说“翻转这个开关”或其他什么,但我确实喜欢这些类型的......“谜题”,我想我会称之为它们。当然,这只有在属性有 getter 和 setter 时才有效。 Setterless 属性需要更多的工作来构建正确的A.CallTo。没什么大不了的,只是有点烦人。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-05
  • 1970-01-01
  • 2014-05-16
  • 1970-01-01
  • 2012-06-27
  • 2011-05-07
  • 1970-01-01
相关资源
最近更新 更多