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:

var mvm = fixture.Build<MyViewModel>()
    .Without(s => s.SelectedItem)
    .CreateAnonymous();

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:

var mvm = fixture.Build<MyViewModel>()
    .OmitAutoProperties()
    .CreateAnonymous();

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.


Comments

Murali
Hi Mark,

Can you please help in creating the class which has an array of other types. With Autofixture , the array size is default to 2 null tems.

For eg:

Here is the my class definition:

class MyClassA
{

public MyClassB[] items;
public MyClassC c;
public MyClassD d;
}

class MyclassB
{
public int x;
public string y;

}
when i use Autofixture for creating MyClass c,d are created and b array with 2 items but with each item null instead of intantiated MyclassB objects. How do i get an Myclass with MyclassB array .
Thanks for your help in advance.

Murali
2009-12-04 22:00 UTC
Hi Murali

Thank you for your question! It prompted me to write a new blog post that provides possible solutions to your question: Building and assigning arrays with AutoFixture.

I hope it answers your question. If not then please write again.
2009-12-05 00:45 UTC
Simple
Hi Mark,

which MVVM Frameworks do you prefer? Or if you dont use Framerworks - which one can you recommend?
2012-05-10 13:22 UTC
FWIW, I've found Knockout.js pretty decent so far, but that's probably not what you had in mind?

For WPF, I don't think an additional framework is warranted for MVVM; for Silverlight, I have no opinion.
2012-05-10 15:02 UTC
Simple
Yes you are right - my question was about MVVM Framework for WPF.. )

2012-05-10 20:16 UTC
Simple
Hello again Mark!

Do you use some kind of GUI-Tests? To simulate users cliks etc..

2012-05-14 07:09 UTC
2012-05-14 08:23 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or Google Plus, or somewhere else with a permalink. Ping me with the link, and I may add it as a comment.

Published

Tuesday, 25 August 2009 18:27:39 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!