我一直在研究,我开始认为这是可能的,但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
类,使用Autofixture实例化并充当MySpace.State
,即使它是假的。
如果我正确理解了这个问题,那么目的是通过让第三方使用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,虽然我怀疑你不需要这个单元测试,你可以忽略第一个单词 测试 数据生成器......