【发布时间】:2014-06-26 16:36:58
【问题描述】:
我正在尝试学习 AutoFixture,并且我已经设置了 xUnit 和 NSubstitute 以及 AutoFixture 设置来自动模拟带有假货的属性(使用 AutoFixture.AutoNSubstitute)。也就是说,如果我有如下界面
public interface IFoo
{
IBar1 Bar1 {get;}
IBar2 Bar2 {get; set;}
}
尝试解析 IFoo 将自动解析并填充 Bar1 和 Bar2。
对于具有接口、具体对象或结构类型属性的对象,一切都适用。但是,我在让 AutoFixture 自动创建抽象类型的属性时遇到问题。
我尝试使用 TypeRelay 作为抽象类型,所以
fixture.Customizations.Add(new TypeRelay(typeof (AbstractBase), typeof (ConcreteChild)));
我试过这样指定,
fixture.Customize<AbstractBase>(
composer =>
composer.FromFactory(
(string ChildParam1, string ChildParam2) => new ConcreteChild(ConcreteChildParam1, ConcreteChildParam2)));
我尝试过使用各种自定义样本生成器
通过属性类型解析:
var pi = request as PropertyInfo;
if (pi != null &&
pi.PropertyType == typeof(AbstractBase))
return context.Resolve(typeof(ConcreteChild));
return new NoSpecimen(request);
通过类类型解析:
var pi = request as Type;
if (pi != null &&
pi == typeof (AbstractBase))
return context.Resolve(typeof(ConcreteChild));
return new NoSpecimen(request);
以上两种方案我也试过context.Create<ConcreteChild>()
最后我尝试使用Register<AbstractBase>(fixture.Create<ConcreteChild>); 语法。
它们似乎都不能自动填充对象的属性。
令人恼火的是,我可以在一个单独的测试中明确地fixture.Create<AbstractBase>(); 并获得ConcreteChild,然后手动卡住所有东西,但这会违背 AutoFixture 的目的吗?
有什么想法吗?
更新:
抽象类。我已经修剪了大部分无关紧要的东西,留下了我假设它被调用的 ctor 代码?
public abstract class ChatEntityId
{
private string _localName;
protected ChatEntityId(string chatRoomName, string entityUid, ChatProtocol protocol)
{
ErrorChecker.NormalizeToNullIfNotSet(ref chatRoomName);
ErrorChecker.NormalizeToNullIfNotSet(ref entityUid);
if (chatRoomName == null && entityUid == null)
{
throw new ArgumentException("Both chatRoomName and entityUid may not be null at the same time.");
}
ChatRoomName = chatRoomName;
EntityUid = entityUid;
Protocol = protocol;
}
public string ChatRoomName { get; private set; }
public string EntityUid { get; private set; }
public bool Equals(ChatEntityId chatEntityId) { }
public override bool Equals(object obj) { }
public override int GetHashCode() {}
public string LocalName { get; }
public ChatProtocol Protocol { get; private set; }
public override string ToString() { }
}
ChatProtocol 是一个枚举,相当标准。
AutoPopulatedProperty ICustomization
public virtual void Customize(IFixture fixture)
{
fixture.Customize(new DomainCustomization());
// Replacement for the AutoNSubstituteCustomization, this Postprocessor will automatically create fake objects on properties.
fixture.ResidueCollectors.Add(
new Postprocessor(
new NSubstituteBuilder(
new MethodInvoker(
new NSubstituteMethodQuery())),
new AutoPropertiesCommand(
new PropertiesOnlySpecification())));
}
private class PropertiesOnlySpecification : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
return request is PropertyInfo;
}
}
【问题讨论】:
-
能否提供抽象类型的代码?
-
已更新。我不一定确定我是否清楚地解释了实际问题(我不确定),我昨天有一个想法/实现,我认为 AutoFixture 的工作方式可能是一个错误的假设。我假设用于自动填充假对象的后处理器会返回并从夹具发出请求,但我不确定它是否正在这样做?我已经添加了我从其他地方提取的代码,因为它具有 AutoNSubstitute 自动模拟属性。
-
this gist 是否重现您的案例?
-
如果这个要点重现了这个案例,它看起来像是 AutoFixture 和 NSubstitute 之间交互的限制。它可能类似于this AutoMoq behaviour,但我不知道属性的默认 NSubstitute 行为是什么......
-
是的,完全正确。顺便说一句,我对 NSubstitute 的默认行为也不太了解。 OOTB,目前只有 AutoFixture.AutoFakeItEasy 通过了两个测试。
标签: c# xunit.net autofixture nsubstitute