Autofixture,class 作为生成的 class 对象?
Autofixture, class as the generated class object?
我一直在研究,我开始认为这是可能的,但 Autofixture 有一些漏洞。
写一个假的 class,我在合法 class 中有一个 States
class,我想在 [=35= 上定义为 Autofixture 生成的对象] 在我的 fakes 项目中实例化 class。
类似于以下内容:
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
}
但我不是在摸索如何让它真正起作用。我这里的方向是否正确?
编辑:澄清一下,这不是为了测试。这是为了向第三方提供虚假数据,而不让他们访问我们的真实数据或网络。目标是让我们的假 class 代替真实的库,以便代码相同。所以在我们的示例中,如果我说 MySpace.State state = new MySpace.State()
或 fake.State state = new fake.State()
,我需要返回相同的对象,无论我们指向的是假库还是真实库。由于 Autofixture 创建了一个类型的对象并在您 fixture.Create<MySpace.State>()
时将其交还,我需要一个假的 State
class 来使用 Autofixture 实例化并充当 MySpace.State
即使这是假的。
如果我对问题的理解正确,其目的是通过让第三方使用 Adapter API 来区分内部和外部行为。在那种情况下,我认为您最好的选择是使用静态工厂方法,如下所示:
namespace Ploeh.Whosebug.Q47914153.Geo.Fakes
{
public class State : MySpace.State
{
private State()
{
}
public static State Create()
{
return new Fixture().Build<State>().FromFactory(() => new State()).Create();
}
}
}
请注意构造函数是 private
以防止客户端开发人员创建 'empty' 对象。 (并不是说我认为这是一个好的模式,但这似乎符合 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[=36 中的第一个词=]...
我一直在研究,我开始认为这是可能的,但 Autofixture 有一些漏洞。
写一个假的 class,我在合法 class 中有一个 States
class,我想在 [=35= 上定义为 Autofixture 生成的对象] 在我的 fakes 项目中实例化 class。
类似于以下内容:
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
}
但我不是在摸索如何让它真正起作用。我这里的方向是否正确?
编辑:澄清一下,这不是为了测试。这是为了向第三方提供虚假数据,而不让他们访问我们的真实数据或网络。目标是让我们的假 class 代替真实的库,以便代码相同。所以在我们的示例中,如果我说 MySpace.State state = new MySpace.State()
或 fake.State state = new fake.State()
,我需要返回相同的对象,无论我们指向的是假库还是真实库。由于 Autofixture 创建了一个类型的对象并在您 fixture.Create<MySpace.State>()
时将其交还,我需要一个假的 State
class 来使用 Autofixture 实例化并充当 MySpace.State
即使这是假的。
如果我对问题的理解正确,其目的是通过让第三方使用 Adapter API 来区分内部和外部行为。在那种情况下,我认为您最好的选择是使用静态工厂方法,如下所示:
namespace Ploeh.Whosebug.Q47914153.Geo.Fakes
{
public class State : MySpace.State
{
private State()
{
}
public static State Create()
{
return new Fixture().Build<State>().FromFactory(() => new State()).Create();
}
}
}
请注意构造函数是 private
以防止客户端开发人员创建 'empty' 对象。 (并不是说我认为这是一个好的模式,但这似乎符合 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[=36 中的第一个词=]...