Ignore multiple (complex) properties

Mar 16, 2010 at 8:07 PM

I just found this wonderful framework and it's been very helpful so far.  I'm wondering whether AutoFixture can ignore properties based on certain criteria rather than the individual property names.  I have a rather large object graph and many of these relationships use IEnumerable<>s.  Here's an example of one such object:

public class Contact
public string EmailAddress { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public User Creator { get; set; }
public IEnumerable<Share> Shares { get; set; }
public IEnumerable<Share> SharedFiles { get; set; }
public IEnumerable<Share> SharedFolders { get; set; }

I'm creating anonymous Contacts with the following call:


var contact = _fixtures.Build()
                       .Without(c => c.Creator)
                       .Without(c => c.Shares)
                       .Without(c => c.SharedFiles)
                       .Without(c => c.SharedFolders)


I was thinking it'd be nice if I could set the recursion level to 1 (or something) to preclude my having to specify all of the relations on each of my objects.  Any suggestions you can provide would be most welcome!

Mar 16, 2010 at 11:26 PM

AutoFixture 1.0 doesn't support any sort of criterion-based selection, and in general it (unfortunately) doesn't support open generics. However, we are tracking this issue, so if you think it's important then consider voting for it: http://autofixture.codeplex.com/WorkItem/View.aspx?WorkItemId=3387

AutoFixture 2.0 will have a much more open extensible kernel, so it will allow you to write your own builder that contains special logic for IEnumerable<>, if you would like.

Until then, you may want to take a look at this related [discussion:205101] for hints on how you can currently address this issue.

Another couple of points worth noticing:

As a general rule, the Framework Design Guidelines strongly discourages writable collection properties, so in any case you should consider making your Shares, SharedFiles and SharedFolders properties read-only. It will also remove any need for explicitly opting out of those properties.

You can also create a general customization of the Contact type:

fixture.Customize<Contact>(ob => ob
    .Without(c => c.Creator)
    .Without(c => c.Shares)
    .Without(c => c.SharedFiles)
    .Without(c => c.SharedFolders));

Another alternative is to opt out of Auto-Properties all together and opt in on those properties you want populated, but that's a bit less refactoring-safe, since you might later add more properties to the type, and these will not be filled out in that case:

fixture.Customize<Contact>(ob => ob.OmitAutoProperties().With(c => c.EmailAddress).With(c => c.FirstName).With(c => c.LastName));

However, the best option altogether may to enable the Fixture to create those types (such as the User type).

Please don't hesitate to write if you have further questions.

Mar 17, 2010 at 10:14 PM

Thank you for the detailed comments!  I had been using the Customize() method up until now, however your note about writable collections had me rubbing my forehead wondering why I made those setters in the first place.  At the moment I can't recall any reason at all (let alone a good one), so I think the best solution at the moment is to simply remove them!

Naturally, this makes the customizations somewhat more pleasant.  :-)  Thanks again, and good luck with v2.0!