AutoFixture可以在对象创建时执行委托吗?
我正在寻找自定义AutoFixture的创建时行为,这样我可以在生成和分配夹具的属性后设置一些依赖对象。
例如,假设我有一个自定义User
的方法,因为对于某组测试,其IsDeleted
属性始终必须为false:
public class User { public int Id { get; set; } public string Name { get; set; } public bool IsDeleted { get; set; } } public static ObjectBuilder BuildUser(this Fixture f) { return f.Build().With(u => u.IsDeleted, false); }
(我将ObjectBuilder
交回测试,以便在必要时可以进一步自定义夹具。)
我想要做的是在创建时自动将该用户与其匿名集合关联,但我不能这样做,因为当我将返回值返回给用户时,我还没有生成Id
unit testing正确。 这是我正在尝试做的事情:
public static ObjectBuilder BuildUserIn(this Fixture f, UserCollection uc) { return f.Build() .With(u => u.IsDeleted, false); .AfterCreation(u => { var relation = f.Build() .With(ucm => ucm.UserCollectionId, uc.Id) .With(ucm => ucm.UserId, u.Id) .CreateAnonymous(); Repository.Install(relation); } }
这样的事情可能吗? 或者也许有更好的方法来实现我创建匿名对象图的目标?
对于Build
方法,这是不可能的,也可能永远不会,因为有更好的选择。
首先,永远不必在Build
方法周围编写静态辅助方法。 Build
方法用于真正的一次性初始化,其中需要在事实之前定义属性或字段值。
即想象一个这样的类:
public class MyClass { private string txt; public string SomeWeirdText { get { return this.txt; } set { if (value != "bar") throw new ArgumentException(); this.txt = value; } } }
在这个(人为的)示例中,直接fixture.CreateAnonymous
将要抛出,因为它将尝试为该属性分配除“bar”之外的其他内容。
在一次性场景中,可以使用Build
方法来解决此问题。 一个例子就是将值明确设置为“bar”:
var mc = fixture.Build().With(x => x.SomeWeirdText, "bar").CreateAnonymous();
但是,更简单的是省略该属性:
var mc = fixture.Build().Without(x => x.SomeWeirdText).CreateAnonymous();
但是,一旦你开始想要反复这样做,有更好的选择。 AutoFixture有一个非常复杂和可定制的引擎,用于定义创建事物的方式。
首先,可以将遗漏属性转换为自定义,如下所示:
fixture.Customize(c => c.Without(x => x.SomeWeirdText));
现在,每当fixture创建一个MyClass实例时,它就会完全跳过该属性。 您仍然可以在之后分配值:
var mc = fixture.CreateAnonymous(); my.SomeWeirdText = "bar";
如果您想要更复杂的东西,可以实现自定义的ISpecimenBuilder 。 如果要在创建实例后运行一些自定义代码,可以使用后处理器装饰自己的ISpecimenBuilder并提供委托。 这可能看起来像这样:
fixture.Customizations.Add( new Postprocessor(yourCustomSpecimenBuilder, obj => { */ do something to obj here */ }));
(顺便说一句,你还在使用AutoFixture 1.0吗?IIRC,从那时起就没有一个ObjectBuilder
…)
关于AutoFixture CodePlex网站上有关此主题的有用讨论 。
我相信我的后期处理器定制链接应该可以帮到你。 用法示例:
class AutoControllerDataAttribute : AutoDataAttribute { public AutoControllerDataAttribute() : this( new Fixture() ) { } public AutoControllerDataAttribute( IFixture fixture ) : base( fixture ) { fixture.Customize( new AutoMoqCustomization() ); fixture.Customize( new ApplyControllerContextCustomization() ); } class ApplyControllerContextCustomization : PostProcessWhereIsACustomization { public ApplyControllerContextCustomization() : base( PostProcess ) { } static void PostProcess( Controller controller ) { controller.FakeControllerContext(); // etc. - add stuff you want to happen after the instance has been created
- AutoFixture:PropertyData和异构参数
- AutoFixture无法创建CreateAnonymous MVC Controller
- 如何创建始终在AutoFixture中设置预定义值的类列表?
- 我应该使用AutoFixture来测试我的洋葱的核心元素,它没有依赖性吗?
- AutoFoture与AutoMoq和具体对象注入
- 使用CreateMany()AutoFixture IEnumerable 行为
- 强制AutoFixture使用最贪婪的构造函数
- 如何使用Autofixture创建和填充我的模拟类?
- AutoFixture – 如何调用方法,如何设置autoproperty的私有setter?