Calling Methods While Building Anonymous Variables With AutoFixture by Mark Seemann
Previously, we saw how you can set property values while building anonymous variables with AutoFixture. While I insinuated that I consider this a somewhat atypical scenario, we can now safely venture forth to the truly exotic :)
Imagine that you want to build an anonymous instance of a type that requires you to call a certain method before you can start assigning properties. It's difficult to come up with a reasonable example of this, but although I consider it quite bad design, I've seen interfaces that include an Initialize method that must be called before any other member. In our example, let's call this interface IBadDesign.
Let's say that we have a class called SomeImp that implements IBadDesign. Here's the relevant part of the class:
#region IBadDesign Members public string Message { get { return this.message; } set { if (this.mc == null) { throw new InvalidOperationException("..."); } this.message = value; this.transformedMessage = this.mc.DoStuff(value); } } public void Initialize(MyClass mc) { this.mc = mc; } #endregion
This is a rather ridiculous example, but I couldn't think of a better one. The main point here is that given a brand-new instance of SomeImp, this usage is invalid:
something.Message = "Ploeh";
While the above code snippet will throw an InvalidOperationException, this will work:
something.Initialize(new MyClass()); something.Message = "Ploeh";
The problem is that by default, AutoFixture ignores methods and only assigns properties, which means that this is also going to throw:
var imp = fixture.CreateAnonymous<SomeImp>();
As we saw with properties, we can use the Build method to customize how the type is being created. Properties can be set with the With method, while methods can be invoked with the Do method, so this is all it takes:
var imp = fixture.Build<SomeImp>() .Do(s => s.Initialize(new MyClass())) .CreateAnonymous();
We don't have to explicitly set the Message property, as AutoFixture is going to do this automatically, and all implicit assignments happen after explicit actions defined by With or Do (and in case you were wondering, you can mix With and Do, and ObjectBuilder<T> will preserve the ordering).
In most cases, having to use the Do method probably constitutes a design smell of the SUT, but the method is there if you need it.