Soon after I posted my post on the AutoFixture Custom Builder's Do method, a much better example occurred to me, so let's revisit this feature in light of a more reasonable context.
When I write WPF code, I always use the MVVM pattern. When I need to create a Master/Detail View, I usually model it so that my View Model has a list of available items, and a property that returns the currently selected item. In this way, I can bind the current Detail View to the currently selected item purely through the View Model.
Such a View Model might look like this:
public class MyViewModel
{
private readonly List<MyClass> availableItems;
private MyClass selectedItem;
public MyViewModel()
this.availableItems = new List<MyClass>();
}
public ICollection<MyClass> AvailableItems
get { return this.availableItems; }
public MyClass SelectedItem
get { return this.selectedItem; }
set
if (!this.availableItems.Contains(value))
throw new ArgumentException("...");
this.selectedItem = value;
The main point of interest is that if you attempt to set SelectedItem to an instance that's not contained in the list of available items, an exception will be thrown. That's reasonable behavior, since we want the user to select only from the available items.
By default, AutoFixture works by assigning an Anonymous Value to all writable properties. Since these values are auto-generated, the value AutoFixture is going to assign to SelectedItem will be a new instance of MyClass, and thus not one of the available items. In other words, this will throw an exception:
var mvm = fixture.CreateAnonymous<MyViewModel>();
There are several solutions to this situation, depending on the scenario. If you need an instance with SelectedItem correctly set to a non-null value, you can use the Do method like this:
var mc = fixture.CreateAnonymous<MyClass>();
var mvm = fixture.Build<MyViewModel>()
.Do(x => x.AvailableItems.Add(mc))
.With(x => x.SelectedItem, mc)
.CreateAnonymous();
This first creates an anonymous instance of MyClass, adds it to AvailableItems as part of a customized Builder pipeline and subsequently assigns it to SelectedItem.
Another option is to skip assigning only the SelectedItem property. This is a good option if you don't need that value in a particular test. You can use the Without method to do that:
.Without(s => s.SelectedItem)
This will assign a value to all other writable properties of MyViewModel (if it had had any), except the SelectedItem property. In this case, the value of SelectedItem will be null, since it is being ignored.
Finally you can simply choose to omit all AutoProperties using the OmitAutoProperties method:
.OmitAutoProperties()
In this scenario, only MyViewModel's constructor is being executed, while all writable properties are being ignored.
As you can see, AutoFixture offers great flexibility in providing specialized custom Builders that fit almost any situation.
Remember Me
a@href@title, b, em, i, strike, strong
Page rendered at Saturday, February 04, 2012 10:34:59 PM (Romance Standard Time, UTC+01:00)
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.