我一直在研究,并且我开始认为这是可能的,但Autofixture有一些rabbitholes。
写一个fakes类,我的合法类中有一个States
类,我想在我的fakes项目类中定义为类实例化的Autofixture生成对象。
如下所示:
namespace Geo.Fakes {
public class State : MySpace.State, {
public cBRCState() : base() {
this = new Fixture<MySpace.State>().Create(); //can't do this
}
}
现在,显然,您无法指定this
,因为它是只读的。我想过实现IFixture
或ISpecimenBuilder
接口并将构造函数更改为
public State () : base() {
this.Create<MySpace.State>();
}
...
public object Create(object request, ISpecimenContext context) {
return new Fixture().Create<MySpace.State>(); //can't do this either, recursive
}
但是我并没有意识到如何让它真正发挥作用。我甚至在这里朝着正确的方向前进吗?
编辑:澄清一下,这不是用于测试。这是为了向第三方提供虚假数据而不让他们访问我们的真实数据或网络。我们的目标是让我们的假类代替真正的库,以便代码是相同的。因此,在我们的示例中,如果我说MySpace.State state = new MySpace.State()
或fake.State state = new fake.State()
,我需要返回相同的对象,无论我们是指向假库还是真实库。而且由于Autofixture会创建一个类型的对象并在fixture.Create<MySpace.State>()
时将其移交给我,我需要有一个假的State
类,使用自动混合进行实例化并充当MySpace.State
,即使它是rails c
。是假的。
答案 0 :(得分:2)
如果我正确理解了这个问题,目的是通过让第三方使用Adapter API来区分内部和外部行为。在这种情况下,我认为您最好的选择是使用静态工厂方法,如下所示:
namespace Ploeh.StackOverflow.Q47914153.Geo.Fakes
{
public class State : MySpace.State
{
private State()
{
}
public static State Create()
{
return new Fixture().Build<State>().FromFactory(() => new State()).Create();
}
}
}
请注意,构造函数是private
,以防止客户端开发人员创建“空”对象。 (并不是说我认为这是一个很好的模式,但这似乎符合OP中的描述。最终,这是你的脚。)
默认情况下,AutoFixture将忽略私有构造函数,其第二个选项是查找静态工厂方法...如Create
。如果您只是使用Fixture.Create
,那么确实会创建一个无限递归。避免这种情况的诀窍是使用Build
API并结合FromFactory
,因为默认情况下AutoFixture会考虑private
成员禁忌,它仍然会愉快地调用() => new State()
lambda表达。
此测试通过:
[Fact]
public void DemoOfFactory()
{
var state = Geo.Fakes.State.Create();
Assert.IsType<Geo.Fakes.State>(state);
Assert.NotEqual(default(string), state.TheText);
Assert.NotEqual(default(int), state.TheNumber);
}
虽然我不确定我是否理解这种情况下的所有要求,但总体方法的某些内容对我来说并不合适。当我隐藏复杂的创作逻辑时,我总是感到不安。
您可以使用Builder模式,而不是依赖随机值生成和继承吗?这是一个article about Test Data Builders,虽然我怀疑你不需要这个用于单元测试,你可以忽略 Test Data Builder 中的第一个单词...... < / p>