一般来说,我有两种常见类型的对象Strikes和Options.这些已被抽象为IStrike和IOption两个接口.
假设IOption有以下几个字段,实际上大约有10倍,但我们可以使用以下三个来说明问题.
interface IOption { double Bid{get;set;} double Ask{get;set;} double ImpliedVol{get;set;} } interface IStrike { IOption Call{get;set;} IOption Put{get;set;} }
现在,这一切都很好,但是让我说我已经有了以下方法来对IOption隐含卷执行一些“数学”
public double SquareImpliedVol(IOption opt) { return Math.Pow(opt.ImpliedVol,2); }
同样,不是问题,但是当我为我的测试编写一些模拟对象时,我不清楚是否需要实现Bid和Ask.我没有,但我不知道除非我知道SquareImpliedVol里面的内容,这意味着我正在编写针对代码的测试,这很糟糕.
所以为了解决这个问题,我可以创建另一个只包含ImpliedVol属性的接口IOptionImpliedVol,然后让IOption继承自IOptionImpliedVol,就像这样
interface IOption : IOptionImpliedVol { double Bid{get;set;} double Ask{get;set;} }
然后我们可以切换SquareImpliedVol
public double SquareImpliedVol(IOptionImpliedVol opt) { return Math.Pow(opt.ImpliedVol,2); }
而且我们很棒.我可以写模拟对象,一切都很甜蜜.除了….我想编写一个将在List上运行的方法,但我需要的唯一属性是IStrike,它是Call.ImpliedVol和Put.ImpliedVol.我想创造类似的东西
interface IStrikeImpliedVol { IOptionImpliedVol Call; IOptionImpliedVol Put; }
然后我也可以
interface IStrike : IStrikeImpliedVol { IOption Call; IOption Put; }
除非这不合法.我觉得必须有某种设计模式,我可以解决这个问题,但我陷入了某种组合和继承的网络.
我认为你的初始设计有两个接口是正确的.你说你必须知道何时设置买入/卖出以及何时不在测试中设置它并且困扰你.让我们试着从其他角度来看待它.你正在为一些函数编写测试(假设它再次是你的SquareImpliedVol).您知道正确实现此功能应该只关心ImpliedVol属性,而不关心Bid / Ask,因此您可以将这些留空.如果功能因未设置的Bid / Ask而失败,那么您的单元测试发现了一个问题 – 请高兴.当然,如果空的买入/卖出是Option对象的错误状态,它会有所不同,但在您的情况下这似乎不是问题.
换句话说,我会说你正在编写一个测试,反对你对特定方法应该如何工作的知识,并且这个知识与已经在该函数中编写的代码相关的事实没有任何错误.